summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Auxiliary/cmake-mode.el42
-rw-r--r--Auxiliary/vim/indent/cmake.vim4
-rw-r--r--Auxiliary/vim/syntax/cmake.vim10
-rw-r--r--CMakeLists.txt468
-rw-r--r--CTestCustom.cmake.in6
-rw-r--r--CompileFlags.cmake17
-rw-r--r--Copyright.txt1
-rw-r--r--Help/command/FIND_XXX.txt26
-rw-r--r--Help/command/add_custom_command.rst4
-rw-r--r--Help/command/add_custom_target.rst2
-rw-r--r--Help/command/add_subdirectory.rst9
-rw-r--r--Help/command/block.rst76
-rw-r--r--Help/command/build_command.rst8
-rw-r--r--Help/command/cmake_language.rst28
-rw-r--r--Help/command/cmake_policy.rst41
-rw-r--r--Help/command/continue.rst6
-rw-r--r--Help/command/ctest_build.rst6
-rw-r--r--Help/command/ctest_run_script.rst6
-rw-r--r--Help/command/ctest_start.rst2
-rw-r--r--Help/command/ctest_test.rst10
-rw-r--r--Help/command/enable_language.rst9
-rw-r--r--Help/command/endblock.rst11
-rw-r--r--Help/command/export.rst16
-rw-r--r--Help/command/file.rst7
-rw-r--r--Help/command/find_package.rst53
-rw-r--r--Help/command/foreach.rst8
-rw-r--r--Help/command/function.rst6
-rw-r--r--Help/command/get_test_property.rst3
-rw-r--r--Help/command/if.rst7
-rw-r--r--Help/command/install.rst49
-rw-r--r--Help/command/message.rst7
-rw-r--r--Help/command/return.rst85
-rw-r--r--Help/command/set.rst19
-rw-r--r--Help/command/target_compile_definitions.rst6
-rw-r--r--Help/command/target_compile_options.rst6
-rw-r--r--Help/command/target_include_directories.rst6
-rw-r--r--Help/command/target_link_directories.rst11
-rw-r--r--Help/command/target_link_libraries.rst4
-rw-r--r--Help/command/target_link_options.rst6
-rw-r--r--Help/command/target_precompile_headers.rst6
-rw-r--r--Help/command/target_sources.rst85
-rw-r--r--Help/command/try_compile.rst151
-rw-r--r--Help/command/try_run.rst96
-rw-r--r--Help/command/while.rst8
-rw-r--r--Help/cpack_gen/archive.rst6
-rw-r--r--Help/cpack_gen/deb.rst14
-rw-r--r--Help/cpack_gen/external.rst4
-rw-r--r--Help/cpack_gen/freebsd.rst12
-rw-r--r--Help/cpack_gen/ifw.rst2
-rw-r--r--Help/cpack_gen/nsis.rst31
-rw-r--r--Help/cpack_gen/nuget.rst20
-rw-r--r--Help/cpack_gen/rpm.rst4
-rw-r--r--Help/cpack_gen/wix.rst2
-rw-r--r--Help/dev/experimental.rst30
-rw-r--r--Help/envvar/ASM_DIALECTFLAGS.rst19
-rw-r--r--Help/envvar/CFLAGS.rst11
-rw-r--r--Help/envvar/CMAKE_GENERATOR.rst6
-rw-r--r--Help/envvar/CMAKE_GENERATOR_PLATFORM.rst2
-rw-r--r--Help/envvar/CMAKE_GENERATOR_TOOLSET.rst2
-rw-r--r--Help/envvar/CSFLAGS.rst11
-rw-r--r--Help/envvar/CTEST_PROGRESS_OUTPUT.rst4
-rw-r--r--Help/envvar/CUDAFLAGS.rst11
-rw-r--r--Help/envvar/CXXFLAGS.rst11
-rw-r--r--Help/envvar/DESTDIR.rst5
-rw-r--r--Help/envvar/FFLAGS.rst11
-rw-r--r--Help/envvar/HIPFLAGS.rst11
-rw-r--r--Help/envvar/ISPCFLAGS.rst11
-rw-r--r--Help/envvar/LANG_FLAGS.txt6
-rw-r--r--Help/envvar/RCFLAGS.rst11
-rw-r--r--Help/envvar/SSL_CERT_DIR.rst9
-rw-r--r--Help/envvar/SSL_CERT_FILE.rst9
-rw-r--r--Help/generator/Green Hills MULTI.rst12
-rw-r--r--Help/generator/Ninja Multi-Config.rst4
-rw-r--r--Help/generator/Visual Studio 10 2010.rst54
-rw-r--r--Help/generator/Visual Studio 11 2012.rst13
-rw-r--r--Help/generator/Visual Studio 12 2013.rst4
-rw-r--r--Help/generator/Visual Studio 14 2015.rst4
-rw-r--r--Help/generator/Visual Studio 15 2017.rst4
-rw-r--r--Help/generator/Visual Studio 16 2019.rst4
-rw-r--r--Help/generator/Visual Studio 17 2022.rst4
-rw-r--r--Help/generator/Visual Studio 9 2008.rst2
-rw-r--r--Help/generator/Xcode.rst14
-rw-r--r--Help/guide/ide-integration/index.rst17
-rw-r--r--Help/guide/tutorial/A Basic Starting Point.rst468
-rw-r--r--Help/guide/tutorial/Adding Export Configuration.rst2
-rw-r--r--Help/guide/tutorial/Adding Generator Expressions.rst294
-rw-r--r--Help/guide/tutorial/Adding Support for a Testing Dashboard.rst20
-rw-r--r--Help/guide/tutorial/Adding System Introspection.rst12
-rw-r--r--Help/guide/tutorial/Adding Usage Requirements for a Library.rst151
-rw-r--r--Help/guide/tutorial/Adding a Custom Command and Generated File.rst14
-rw-r--r--Help/guide/tutorial/Adding a Library.rst465
-rw-r--r--Help/guide/tutorial/Complete/CMakeLists.txt3
-rw-r--r--Help/guide/tutorial/Complete/License.txt2
-rw-r--r--Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt3
-rw-r--r--Help/guide/tutorial/Installing and Testing.rst330
-rw-r--r--Help/guide/tutorial/Packaging Debug and Release.rst8
-rw-r--r--Help/guide/tutorial/Packaging an Installer.rst10
-rw-r--r--Help/guide/tutorial/Selecting Static or Shared Libraries.rst14
-rw-r--r--Help/guide/tutorial/Step1/CMakeLists.txt16
-rw-r--r--Help/guide/tutorial/Step1/TutorialConfig.h.in2
-rw-r--r--Help/guide/tutorial/Step1/tutorial.cxx7
-rw-r--r--Help/guide/tutorial/Step10/CMakeLists.txt33
-rw-r--r--Help/guide/tutorial/Step10/License.txt2
-rw-r--r--Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt71
-rw-r--r--Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h15
-rw-r--r--Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx4
-rw-r--r--Help/guide/tutorial/Step10/TutorialConfig.h.in1
-rw-r--r--Help/guide/tutorial/Step10/tutorial.cxx15
-rw-r--r--Help/guide/tutorial/Step11/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/Step11/License.txt2
-rw-r--r--Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt5
-rw-r--r--Help/guide/tutorial/Step11/tutorial.cxx1
-rw-r--r--Help/guide/tutorial/Step12/CMakeLists.txt3
-rw-r--r--Help/guide/tutorial/Step12/License.txt2
-rw-r--r--Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt3
-rw-r--r--Help/guide/tutorial/Step2/CMakeLists.txt23
-rw-r--r--Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt2
-rw-r--r--Help/guide/tutorial/Step2/TutorialConfig.h.in2
-rw-r--r--Help/guide/tutorial/Step2/tutorial.cxx8
-rw-r--r--Help/guide/tutorial/Step3/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step4/CMakeLists.txt26
-rw-r--r--Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt2
-rw-r--r--Help/guide/tutorial/Step5/CMakeLists.txt64
-rw-r--r--Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt13
-rw-r--r--Help/guide/tutorial/Step6/CMakeLists.txt17
-rw-r--r--Help/guide/tutorial/Step6/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt30
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx25
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx8
-rw-r--r--Help/guide/tutorial/Step7/CMakeLists.txt19
-rw-r--r--Help/guide/tutorial/Step7/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step7/License.txt2
-rw-r--r--Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt29
-rw-r--r--Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx25
-rw-r--r--Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx9
-rw-r--r--Help/guide/tutorial/Step8/CMakeLists.txt28
-rw-r--r--Help/guide/tutorial/Step8/License.txt2
-rw-r--r--Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt52
-rw-r--r--Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx17
-rw-r--r--Help/guide/tutorial/Step9/CMakeLists.txt24
-rw-r--r--Help/guide/tutorial/Step9/License.txt2
-rw-r--r--Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt11
-rw-r--r--Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx19
-rw-r--r--Help/guide/tutorial/Step9/MathFunctions/mysqrt.h6
-rw-r--r--Help/guide/tutorial/index.rst4
-rw-r--r--Help/guide/user-interaction/index.rst107
-rw-r--r--Help/manual/OPTIONS_BUILD.txt103
-rw-r--r--Help/manual/OPTIONS_HELP.txt68
-rw-r--r--Help/manual/ccmake.1.rst4
-rw-r--r--Help/manual/cmake-buildsystem.7.rst8
-rw-r--r--Help/manual/cmake-commands.7.rst2
-rw-r--r--Help/manual/cmake-env-variables.7.rst2
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst38
-rw-r--r--Help/manual/cmake-generators.7.rst16
-rw-r--r--Help/manual/cmake-gui.1.rst16
-rw-r--r--Help/manual/cmake-language.7.rst2
-rw-r--r--Help/manual/cmake-modules.7.rst2
-rw-r--r--Help/manual/cmake-policies.7.rst10
-rw-r--r--Help/manual/cmake-presets.7.rst606
-rw-r--r--Help/manual/cmake-properties.7.rst24
-rw-r--r--Help/manual/cmake-qt.7.rst2
-rw-r--r--Help/manual/cmake-toolchains.7.rst72
-rw-r--r--Help/manual/cmake-variables.7.rst48
-rw-r--r--Help/manual/cmake.1.rst533
-rw-r--r--Help/manual/cpack.1.rst52
-rw-r--r--Help/manual/ctest.1.rst465
-rw-r--r--Help/manual/presets/example.json34
-rw-r--r--Help/manual/presets/schema.json405
-rw-r--r--Help/module/FindOpenSP.rst1
-rw-r--r--Help/module/FindSDL_gfx.rst1
-rw-r--r--Help/policy/CMP0058.rst5
-rw-r--r--Help/policy/CMP0140.rst17
-rw-r--r--Help/policy/CMP0141.rst55
-rw-r--r--Help/policy/CMP0142.rst27
-rw-r--r--Help/prop_dir/SYSTEM.rst10
-rw-r--r--Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst5
-rw-r--r--Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst125
-rw-r--r--Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst2
-rw-r--r--Help/prop_test/FIXTURES_REQUIRED.rst9
-rw-r--r--Help/prop_test/LABELS.rst2
-rw-r--r--Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst8
-rw-r--r--Help/prop_tgt/CONFIG_POSTFIX.rst10
-rw-r--r--Help/prop_tgt/CUDA_STANDARD.rst6
-rw-r--r--Help/prop_tgt/CXX_MODULE_DIRS.rst19
-rw-r--r--Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst19
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst19
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst21
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst20
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst20
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst21
-rw-r--r--Help/prop_tgt/CXX_MODULE_SET.rst20
-rw-r--r--Help/prop_tgt/CXX_MODULE_SETS.rst18
-rw-r--r--Help/prop_tgt/CXX_MODULE_SET_NAME.rst20
-rw-r--r--Help/prop_tgt/CXX_STANDARD.rst6
-rw-r--r--Help/prop_tgt/EXPORT_NO_SYSTEM.rst11
-rw-r--r--Help/prop_tgt/HIP_STANDARD.rst6
-rw-r--r--Help/prop_tgt/IMPORTED_NO_SYSTEM.rst12
-rw-r--r--Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst18
-rw-r--r--Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst18
-rw-r--r--Help/prop_tgt/LANG_CLANG_TIDY.rst18
-rw-r--r--Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst5
-rw-r--r--Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt16
-rw-r--r--Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst33
-rw-r--r--Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt5
-rw-r--r--Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst4
-rw-r--r--Help/prop_tgt/OBJCXX_STANDARD.rst6
-rw-r--r--Help/prop_tgt/SYSTEM.rst22
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_COMMAND.rst2
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst2
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst2
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst2
-rw-r--r--Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst2
-rw-r--r--Help/prop_tgt/VS_KEYWORD.rst2
-rw-r--r--Help/prop_tgt/XCODE_GENERATE_SCHEME.rst4
-rw-r--r--Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst14
-rw-r--r--Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst14
-rw-r--r--Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst13
-rw-r--r--Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst22
-rw-r--r--Help/release/3.0.rst2
-rw-r--r--Help/release/3.11.rst2
-rw-r--r--Help/release/3.12.rst4
-rw-r--r--Help/release/3.20.rst6
-rw-r--r--Help/release/3.21.rst14
-rw-r--r--Help/release/3.23.rst11
-rw-r--r--Help/release/3.24.rst36
-rw-r--r--Help/release/3.25.rst240
-rw-r--r--Help/release/3.3.rst2
-rw-r--r--Help/release/3.4.rst2
-rw-r--r--Help/release/3.7.rst2
-rw-r--r--Help/release/index.rst1
-rw-r--r--Help/variable/BSD.rst7
-rw-r--r--Help/variable/CMAKE_ANDROID_API.rst7
-rw-r--r--Help/variable/CMAKE_BINARY_DIR.rst2
-rw-r--r--Help/variable/CMAKE_CFG_INTDIR.rst2
-rw-r--r--Help/variable/CMAKE_COMMAND.rst2
-rw-r--r--Help/variable/CMAKE_CPACK_COMMAND.rst6
-rw-r--r--Help/variable/CMAKE_CTEST_COMMAND.rst6
-rw-r--r--Help/variable/CMAKE_CURRENT_BINARY_DIR.rst2
-rw-r--r--Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst2
-rw-r--r--Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst2
-rw-r--r--Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst2
-rw-r--r--Help/variable/CMAKE_FIND_DEBUG_MODE.rst2
-rw-r--r--Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst2
-rw-r--r--Help/variable/CMAKE_GENERATOR.rst2
-rw-r--r--Help/variable/CMAKE_GENERATOR_PLATFORM.rst2
-rw-r--r--Help/variable/CMAKE_GENERATOR_TOOLSET.rst2
-rw-r--r--Help/variable/CMAKE_HOST_BSD.rst7
-rw-r--r--Help/variable/CMAKE_HOST_LINUX.rst6
-rw-r--r--Help/variable/CMAKE_INSTALL_PREFIX.rst5
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER.rst3
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_ID.rst93
-rw-r--r--Help/variable/CMAKE_LANG_FLAGS.rst10
-rw-r--r--Help/variable/CMAKE_MAKE_PROGRAM.rst4
-rw-r--r--Help/variable/CMAKE_MESSAGE_CONTEXT.rst2
-rw-r--r--Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst10
-rw-r--r--Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst36
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst7
-rw-r--r--Help/variable/CMAKE_SCRIPT_MODE_FILE.rst4
-rw-r--r--Help/variable/CMAKE_SOURCE_DIR.rst2
-rw-r--r--Help/variable/CMAKE_TASKING_TOOLSET.rst34
-rw-r--r--Help/variable/CMAKE_VS_DEVENV_COMMAND.rst2
-rw-r--r--Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst2
-rw-r--r--Help/variable/CMAKE_WARN_DEPRECATED.rst3
-rw-r--r--Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst4
-rw-r--r--Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst13
-rw-r--r--Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst13
-rw-r--r--Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst12
-rw-r--r--Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst13
-rw-r--r--Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst2
-rw-r--r--Help/variable/CTEST_CONFIGURATION_TYPE.rst2
-rw-r--r--Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst2
-rw-r--r--Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt9
-rw-r--r--Help/variable/LINUX.rst6
-rw-r--r--Modules/CMakeCXXCompilerId.cpp.in1
-rw-r--r--Modules/CMakeCompilerIdDetection.cmake1
-rw-r--r--Modules/CMakeDependentOption.cmake2
-rw-r--r--Modules/CMakeDetermineASMCompiler.cmake7
-rw-r--r--Modules/CMakeDetermineCSharpCompiler.cmake2
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake5
-rw-r--r--Modules/CMakeDetermineCompileFeatures.cmake19
-rw-r--r--Modules/CMakeDetermineCompilerABI.cmake10
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake10
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake36
-rw-r--r--Modules/CMakeDetermineHIPCompiler.cmake1
-rw-r--r--Modules/CMakeDetermineVSServicePack.cmake6
-rw-r--r--Modules/CMakeFindBinUtils.cmake2
-rw-r--r--Modules/CMakeFindFrameworks.cmake9
-rw-r--r--Modules/CMakeHIPInformation.cmake2
-rw-r--r--Modules/CMakeParseImplicitLinkInfo.cmake7
-rw-r--r--Modules/CMakePlatformId.h.in24
-rw-r--r--Modules/CMakeSwiftInformation.cmake2
-rw-r--r--Modules/CMakeSystemSpecificInformation.cmake2
-rw-r--r--Modules/CMakeTestCCompiler.cmake7
-rw-r--r--Modules/CMakeTestCSharpCompiler.cmake18
-rw-r--r--Modules/CMakeTestCUDACompiler.cmake7
-rw-r--r--Modules/CMakeTestCXXCompiler.cmake11
-rw-r--r--Modules/CMakeTestFortranCompiler.cmake14
-rw-r--r--Modules/CMakeTestHIPCompiler.cmake7
-rw-r--r--Modules/CMakeTestOBJCCompiler.cmake7
-rw-r--r--Modules/CMakeTestOBJCXXCompiler.cmake7
-rw-r--r--Modules/CMakeTestSwiftCompiler.cmake8
-rw-r--r--Modules/CPack.cmake55
-rw-r--r--Modules/CPackComponent.cmake2
-rw-r--r--Modules/CPackIFW.cmake44
-rw-r--r--Modules/CTest.cmake2
-rw-r--r--Modules/CTestTargets.cmake2
-rw-r--r--Modules/CTestUseLaunchers.cmake7
-rw-r--r--Modules/CheckCXXSymbolExists.cmake2
-rw-r--r--Modules/CheckFortranFunctionExists.cmake7
-rw-r--r--Modules/CheckFunctionExists.cmake8
-rw-r--r--Modules/CheckIPOSupported.cmake46
-rw-r--r--Modules/CheckIncludeFile.cmake7
-rw-r--r--Modules/CheckIncludeFileCXX.cmake7
-rw-r--r--Modules/CheckIncludeFiles.cmake17
-rw-r--r--Modules/CheckLibraryExists.cmake8
-rw-r--r--Modules/CheckPrototypeDefinition.cmake9
-rw-r--r--Modules/CheckSymbolExists.cmake28
-rw-r--r--Modules/CheckTypeSize.cmake12
-rw-r--r--Modules/CheckVariableExists.cmake3
-rw-r--r--Modules/Compiler/Clang-CUDA.cmake4
-rw-r--r--Modules/Compiler/Clang.cmake3
-rw-r--r--Modules/Compiler/IAR-CXX.cmake4
-rw-r--r--Modules/Compiler/IntelLLVM-FindBinUtils.cmake45
-rw-r--r--Modules/Compiler/IntelLLVM.cmake21
-rw-r--r--Modules/Compiler/MSVC-CXX.cmake13
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake24
-rw-r--r--Modules/Compiler/Tasking-ASM.cmake7
-rw-r--r--Modules/Compiler/Tasking-C.cmake47
-rw-r--r--Modules/Compiler/Tasking-CXX.cmake31
-rw-r--r--Modules/Compiler/Tasking-DetermineCompiler.cmake10
-rw-r--r--Modules/Compiler/Tasking-FindBinUtils.cmake18
-rw-r--r--Modules/Compiler/Tasking.cmake54
-rw-r--r--Modules/ExternalProject.cmake23
-rw-r--r--Modules/ExternalProject/gitupdate.cmake.in38
-rw-r--r--Modules/FetchContent.cmake26
-rw-r--r--Modules/FindAVIFile.cmake2
-rw-r--r--Modules/FindBLAS.cmake13
-rw-r--r--Modules/FindBacktrace.cmake2
-rw-r--r--Modules/FindCUDA.cmake4
-rw-r--r--Modules/FindCUDA/select_compute_arch.cmake4
-rw-r--r--Modules/FindCUDAToolkit.cmake80
-rw-r--r--Modules/FindCURL.cmake5
-rw-r--r--Modules/FindCoin3D.cmake4
-rw-r--r--Modules/FindCxxTest.cmake2
-rw-r--r--Modules/FindDCMTK.cmake11
-rw-r--r--Modules/FindDevIL.cmake2
-rw-r--r--Modules/FindDoxygen.cmake60
-rw-r--r--Modules/FindGDAL.cmake2
-rw-r--r--Modules/FindGLEW.cmake27
-rw-r--r--Modules/FindGLUT.cmake74
-rw-r--r--Modules/FindGTK2.cmake1
-rw-r--r--Modules/FindHDF5.cmake6
-rw-r--r--Modules/FindICU.cmake12
-rw-r--r--Modules/FindLAPACK.cmake14
-rw-r--r--Modules/FindLTTngUST.cmake2
-rw-r--r--Modules/FindLibArchive.cmake3
-rw-r--r--Modules/FindMFC.cmake12
-rw-r--r--Modules/FindMPI.cmake156
-rw-r--r--Modules/FindMatlab.cmake26
-rw-r--r--Modules/FindOpenACC.cmake47
-rw-r--r--Modules/FindOpenAL.cmake26
-rw-r--r--Modules/FindOpenGL.cmake2
-rw-r--r--Modules/FindOpenMP.cmake108
-rw-r--r--Modules/FindOpenSP.cmake155
-rw-r--r--Modules/FindOpenSSL.cmake24
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake22
-rw-r--r--Modules/FindPython.cmake6
-rw-r--r--Modules/FindPython/Support.cmake274
-rw-r--r--Modules/FindPython2.cmake2
-rw-r--r--Modules/FindPython3.cmake6
-rw-r--r--Modules/FindRuby.cmake53
-rw-r--r--Modules/FindSDL_gfx.cmake86
-rw-r--r--Modules/FindSDL_image.cmake4
-rw-r--r--Modules/FindSDL_mixer.cmake4
-rw-r--r--Modules/FindSDL_net.cmake4
-rw-r--r--Modules/FindSDL_sound.cmake31
-rw-r--r--Modules/FindSDL_ttf.cmake4
-rw-r--r--Modules/FindSWIG.cmake2
-rw-r--r--Modules/FindThreads.cmake8
-rw-r--r--Modules/FindVulkan.cmake117
-rw-r--r--Modules/FindXCTest.cmake2
-rw-r--r--Modules/FindwxWindows.cmake3
-rw-r--r--Modules/FortranCInterface.cmake8
-rw-r--r--Modules/FortranCInterface/Detect.cmake8
-rw-r--r--Modules/GoogleTest.cmake6
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake30
-rw-r--r--Modules/Internal/CPack/CPackRPM.cmake6
-rw-r--r--Modules/Internal/CheckSourceCompiles.cmake6
-rw-r--r--Modules/Internal/CheckSourceRuns.cmake6
-rw-r--r--Modules/Internal/FeatureTesting.cmake9
-rw-r--r--Modules/Platform/AIX-GNU.cmake4
-rw-r--r--Modules/Platform/AIX-XL.cmake4
-rwxr-xr-xModules/Platform/AIX/ExportImportList46
-rw-r--r--Modules/Platform/DragonFly.cmake1
-rw-r--r--Modules/Platform/FreeBSD.cmake1
-rw-r--r--Modules/Platform/Linux-IntelLLVM.cmake26
-rw-r--r--Modules/Platform/Linux-NVHPC.cmake16
-rw-r--r--Modules/Platform/Linux.cmake12
-rw-r--r--Modules/Platform/NetBSD.cmake1
-rw-r--r--Modules/Platform/OpenBSD.cmake1
-rw-r--r--Modules/Platform/SerenityOS-Clang-ASM.cmake2
-rw-r--r--Modules/Platform/SerenityOS-Clang-C.cmake2
-rw-r--r--Modules/Platform/SerenityOS-Clang-CXX.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-ASM.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-C.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-CXX.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU.cmake24
-rw-r--r--Modules/Platform/SerenityOS.cmake12
-rw-r--r--Modules/Platform/Windows-Clang-HIP.cmake19
-rw-r--r--Modules/Platform/Windows-Clang.cmake85
-rw-r--r--Modules/Platform/Windows-Intel-C.cmake11
-rw-r--r--Modules/Platform/Windows-Intel-CXX.cmake11
-rw-r--r--Modules/Platform/Windows-Intel-Fortran.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM-Fortran.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM.cmake51
-rw-r--r--Modules/Platform/Windows-MSVC.cmake21
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake14
-rw-r--r--Modules/Platform/Windows.cmake4
-rw-r--r--Modules/Platform/kFreeBSD.cmake3
-rw-r--r--Modules/TestBigEndian.cmake18
-rw-r--r--Modules/TestCXXAcceptsFlag.cmake3
-rw-r--r--Modules/TestForANSIForScope.cmake4
-rw-r--r--Modules/TestForSSTREAM.cmake4
-rw-r--r--Modules/TestForSTDNamespace.cmake4
-rw-r--r--Modules/UseJava.cmake2
-rw-r--r--Modules/UseSWIG.cmake4
-rw-r--r--Source/CMakeLists.txt542
-rw-r--r--Source/CMakeVersion.cmake14
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx12
-rw-r--r--Source/CPack/cmCPackConfigure.h.in5
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx7
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx54
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx8
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.h2
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx34
-rw-r--r--Source/CPack/cpack.cxx171
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx12
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h6
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx20
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h5
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx21
-rw-r--r--Source/CTest/cmCTestRunTest.cxx146
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx65
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h13
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx2
-rw-r--r--Source/CTest/cmCTestUploadCommand.h5
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx2
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt2
-rw-r--r--Source/CursesDialog/form/fty_int.c2
-rw-r--r--Source/CursesDialog/form/fty_num.c2
-rw-r--r--Source/LexerParser/cmFortranLexer.cxx377
-rw-r--r--Source/LexerParser/cmFortranLexer.in.l16
-rw-r--r--Source/LexerParser/cmFortranParser.cxx324
-rw-r--r--Source/LexerParser/cmFortranParser.y18
-rw-r--r--Source/Modules/CMakeBuildUtilities.cmake379
-rw-r--r--Source/QtDialog/CMakeLists.txt88
-rw-r--r--Source/QtDialog/FirstConfigure.cxx3
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx12
-rw-r--r--Source/cmArgumentParser.cxx186
-rw-r--r--Source/cmArgumentParser.h400
-rw-r--r--Source/cmArgumentParserTypes.h69
-rw-r--r--Source/cmBlockCommand.cxx197
-rw-r--r--Source/cmBlockCommand.h14
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx12
-rw-r--r--Source/cmCMakeLanguageCommand.cxx35
-rw-r--r--Source/cmCMakePathCommand.cxx134
-rw-r--r--Source/cmCMakePresetsGraph.cxx310
-rw-r--r--Source/cmCMakePresetsGraph.h112
-rw-r--r--Source/cmCMakePresetsGraphInternal.h8
-rw-r--r--Source/cmCMakePresetsGraphReadJSON.cxx92
-rw-r--r--Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx95
-rw-r--r--Source/cmCMakePresetsGraphReadJSONTestPresets.cxx2
-rw-r--r--Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx95
-rw-r--r--Source/cmCTest.cxx18
-rw-r--r--Source/cmCTest.h3
-rw-r--r--Source/cmCommands.cxx16
-rw-r--r--Source/cmCommonTargetGenerator.cxx4
-rw-r--r--Source/cmComputeLinkInformation.cxx48
-rw-r--r--Source/cmConfigure.cmake.h.in13
-rw-r--r--Source/cmCoreTryCompile.cxx937
-rw-r--r--Source/cmCoreTryCompile.h89
-rw-r--r--Source/cmCreateTestSourceList.cxx4
-rw-r--r--Source/cmCurl.cxx11
-rw-r--r--Source/cmCxxModuleMapper.cxx308
-rw-r--r--Source/cmCxxModuleMapper.h85
-rw-r--r--Source/cmDefinePropertyCommand.cxx5
-rw-r--r--Source/cmDocumentation.cxx42
-rw-r--r--Source/cmExecuteProcessCommand.cxx12
-rw-r--r--Source/cmExecutionStatus.h17
-rw-r--r--Source/cmExperimental.cxx63
-rw-r--r--Source/cmExperimental.h21
-rw-r--r--Source/cmExportBuildFileGenerator.cxx98
-rw-r--r--Source/cmExportBuildFileGenerator.h16
-rw-r--r--Source/cmExportCommand.cxx23
-rw-r--r--Source/cmExportFileGenerator.cxx33
-rw-r--r--Source/cmExportFileGenerator.h5
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportInstallFileGenerator.cxx113
-rw-r--r--Source/cmExportInstallFileGenerator.h25
-rw-r--r--Source/cmExportTryCompileFileGenerator.h3
-rw-r--r--Source/cmFileAPICodemodel.cxx16
-rw-r--r--Source/cmFileCommand.cxx434
-rw-r--r--Source/cmFileCopier.cxx44
-rw-r--r--Source/cmFindBase.cxx62
-rw-r--r--Source/cmFindBase.h7
-rw-r--r--Source/cmFindLibraryCommand.cxx33
-rw-r--r--Source/cmFindPackageCommand.cxx1265
-rw-r--r--Source/cmFindPackageCommand.h2
-rw-r--r--Source/cmFindPathCommand.cxx6
-rw-r--r--Source/cmFindProgramCommand.cxx12
-rw-r--r--Source/cmForEachCommand.cxx2
-rw-r--r--Source/cmFunctionBlocker.cxx18
-rw-r--r--Source/cmFunctionBlocker.h2
-rw-r--r--Source/cmFunctionCommand.cxx1
-rw-r--r--Source/cmGeneratedFileStream.cxx18
-rw-r--r--Source/cmGeneratedFileStream.h10
-rw-r--r--Source/cmGeneratorTarget.cxx147
-rw-r--r--Source/cmGeneratorTarget.h35
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx4
-rw-r--r--Source/cmGlobalGenerator.cxx19
-rw-r--r--Source/cmGlobalGenerator.h57
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx546
-rw-r--r--Source/cmGlobalNinjaGenerator.h4
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx200
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h17
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx33
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx13
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h1
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx48
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx220
-rw-r--r--Source/cmGlobalXCodeGenerator.h7
-rw-r--r--Source/cmIfCommand.cxx2
-rw-r--r--Source/cmInstallCommand.cxx157
-rw-r--r--Source/cmInstallCommandArguments.h5
-rw-r--r--Source/cmInstallCxxModuleBmiGenerator.cxx75
-rw-r--r--Source/cmInstallCxxModuleBmiGenerator.h52
-rw-r--r--Source/cmInstallExportGenerator.cxx73
-rw-r--r--Source/cmInstallExportGenerator.h8
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx21
-rw-r--r--Source/cmLinkLineDeviceComputer.h1
-rw-r--r--Source/cmListFileCache.cxx11
-rw-r--r--Source/cmLocalGenerator.cxx104
-rw-r--r--Source/cmLocalGenerator.h17
-rw-r--r--Source/cmLocalNinjaGenerator.cxx26
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx37
-rw-r--r--Source/cmLocalVisualStudio10Generator.h4
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx7
-rw-r--r--Source/cmMacroCommand.cxx2
-rw-r--r--Source/cmMakefile.cxx105
-rw-r--r--Source/cmMakefile.h22
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx27
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx25
-rw-r--r--Source/cmMakefileTargetGenerator.cxx136
-rw-r--r--Source/cmMakefileTargetGenerator.h20
-rw-r--r--Source/cmMessageCommand.cxx65
-rw-r--r--Source/cmMessageType.h16
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx22
-rw-r--r--Source/cmNinjaTargetGenerator.cxx327
-rw-r--r--Source/cmOutputConverter.cxx7
-rw-r--r--Source/cmParseArgumentsCommand.cxx17
-rw-r--r--Source/cmPolicies.h15
-rw-r--r--Source/cmQtAutoGenInitializer.cxx25
-rw-r--r--Source/cmQtAutoGenInitializer.h2
-rw-r--r--Source/cmReturnCommand.cxx44
-rw-r--r--Source/cmScanDepFormat.cxx15
-rw-r--r--Source/cmScanDepFormat.h5
-rw-r--r--Source/cmScriptGenerator.cxx2
-rw-r--r--Source/cmSetPropertyCommand.cxx4
-rw-r--r--Source/cmStandardLevelResolver.cxx35
-rw-r--r--Source/cmState.cxx21
-rw-r--r--Source/cmStatePrivate.h2
-rw-r--r--Source/cmStateSnapshot.cxx29
-rw-r--r--Source/cmStringCommand.cxx5
-rw-r--r--Source/cmSubdirCommand.cxx4
-rw-r--r--Source/cmSystemTools.cxx289
-rw-r--r--Source/cmSystemTools.h74
-rw-r--r--Source/cmTarget.cxx125
-rw-r--r--Source/cmTarget.h10
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx4
-rw-r--r--Source/cmTargetExport.h2
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx8
-rw-r--r--Source/cmTargetPrecompileHeadersCommand.cxx4
-rw-r--r--Source/cmTargetSourcesCommand.cxx47
-rw-r--r--Source/cmTryCompileCommand.cxx61
-rw-r--r--Source/cmTryCompileCommand.h30
-rw-r--r--Source/cmTryRunCommand.cxx355
-rw-r--r--Source/cmTryRunCommand.h44
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx106
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h1
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx92
-rw-r--r--Source/cmWhileCommand.cxx2
-rw-r--r--Source/cmWindowsRegistry.h2
-rw-r--r--Source/cmXCodeScheme.cxx34
-rw-r--r--Source/cm_codecvt.cxx6
-rw-r--r--Source/cm_codecvt.hxx3
-rw-r--r--Source/cmake.cxx297
-rw-r--r--Source/cmake.h54
-rw-r--r--Source/cmake.version.manifest2
-rw-r--r--Source/cmakemain.cxx104
-rw-r--r--Source/cmcldeps.cxx1
-rw-r--r--Source/cmcmd.cxx84
-rw-r--r--Source/kwsys/Directory.cxx39
-rw-r--r--Source/kwsys/SystemTools.cxx103
-rw-r--r--Templates/MSBuild/FlagTables/v10_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v10_Cuda.json112
-rw-r--r--Templates/MSBuild/FlagTables/v11_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v12_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v140_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v141_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v142_CSharp.json6
-rw-r--r--Templates/MSBuild/FlagTables/v143_CSharp.json6
-rw-r--r--Tests/Assembler/CMakeLists.txt6
-rw-r--r--Tests/CMakeLib/CMakeLists.txt6
-rw-r--r--Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt6
-rw-r--r--Tests/CMakeLib/testArgumentParser.cxx340
-rw-r--r--Tests/CMakeLib/testCMExtEnumSet.cxx9
-rw-r--r--Tests/CMakeLists.txt392
-rw-r--r--Tests/CMakeOnly/AllFindModules/CMakeLists.txt13
-rw-r--r--Tests/CMakeTests/CMakeLists.txt15
-rw-r--r--Tests/CMakeTests/CheckSourceTreeTest.cmake.in365
-rw-r--r--Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in89
-rw-r--r--Tests/CTestCoverageCollectGCOV/test.cmake.in5
-rw-r--r--Tests/CTestTestFdSetSize/sleep.c14
-rw-r--r--Tests/CTestUpdateCommon.cmake6
-rw-r--r--Tests/CTestUpdateP4.cmake.in6
-rw-r--r--Tests/CheckSourceTree/CMakeLists.txt6
-rw-r--r--Tests/CheckSourceTree/check.cmake22
-rw-r--r--Tests/CheckSwift.cmake2
-rw-r--r--Tests/CompileFeatures/CMakeLists.txt1
-rw-r--r--Tests/CompileFeatures/genex_test.cpp3
-rw-r--r--Tests/Complex/CMakeLists.txt8
-rw-r--r--Tests/Complex/Executable/complex.cxx2
-rw-r--r--Tests/ComplexOneConfig/CMakeLists.txt8
-rw-r--r--Tests/ComplexOneConfig/Executable/complex.cxx2
-rw-r--r--Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt5
-rw-r--r--Tests/CudaOnly/CMakeLists.txt25
-rw-r--r--Tests/CudaOnly/DeviceLTO/CMakeLists.txt37
-rw-r--r--Tests/CudaOnly/DeviceLTO/file1.cu17
-rw-r--r--Tests/CudaOnly/DeviceLTO/file2.cu5
-rw-r--r--Tests/CudaOnly/DeviceLTO/file3.cu4
-rw-r--r--Tests/CudaOnly/DeviceLTO/main.cu62
-rw-r--r--Tests/CudaOnly/ToolkitMultipleDirs/CMakeLists.txt22
-rw-r--r--Tests/CudaOnly/ToolkitMultipleDirs/main.cu8
-rw-r--r--Tests/CudaOnly/ToolkitMultipleDirs/subdir/CMakeLists.txt2
-rw-r--r--Tests/EnforceConfig.cmake.in4
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt11
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt14
-rw-r--r--Tests/ExternalProject/CMakeLists.txt6
-rw-r--r--Tests/FindOpenAL/CMakeLists.txt10
-rw-r--r--Tests/FindOpenAL/Test/CMakeLists.txt14
-rw-r--r--Tests/FindOpenAL/Test/main.cxx13
-rw-r--r--Tests/FindOpenSP/CMakeLists.txt10
-rw-r--r--Tests/FindOpenSP/Test/CMakeLists.txt16
-rw-r--r--Tests/FindOpenSP/Test/main.cxx55
-rw-r--r--Tests/FindOpenSP/Test/test.sgml7
-rw-r--r--Tests/FindPackageTest/CMakeLists.txt2
-rw-r--r--Tests/FindVulkan/Test/CMakeLists.txt20
-rw-r--r--Tests/FindVulkan/Test/Run-dxc_exe.cmake20
-rw-r--r--Tests/FindVulkan/Test/main-dxc_lib.cxx23
-rw-r--r--Tests/FindVulkan/Test/main-volk.cxx14
-rw-r--r--Tests/FortranModules/Submodules/CMakeLists.txt1
-rw-r--r--Tests/FortranModules/Submodules/main.f907
-rw-r--r--Tests/FortranModules/Submodules/obfuscated_parent.f9033
-rw-r--r--Tests/FortranModules/test_module_main.f902
-rw-r--r--Tests/FunctionTest/CMakeLists.txt4
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt54
-rw-r--r--Tests/LoadCommand/CMakeCommands/cmTestCommand.c17
-rw-r--r--Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c17
-rw-r--r--Tests/MSVCDebugInformationFormat/CMakeLists.txt81
-rw-r--r--Tests/MSVCDebugInformationFormat/override-C.cmake7
-rw-r--r--Tests/MSVCDebugInformationFormat/override-CUDA.cmake6
-rw-r--r--Tests/MSVCDebugInformationFormat/override-CXX.cmake7
-rw-r--r--Tests/MSVCDebugInformationFormat/override-Fortran.cmake4
-rw-r--r--Tests/MSVCDebugInformationFormat/verify.F901
-rw-r--r--Tests/MSVCDebugInformationFormat/verify.c1
-rw-r--r--Tests/MSVCDebugInformationFormat/verify.cu1
-rw-r--r--Tests/MSVCDebugInformationFormat/verify.cxx1
-rw-r--r--Tests/MSVCDebugInformationFormat/verify.h29
-rw-r--r--Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt32
-rw-r--r--Tests/Module/CheckIPOSupported-CUDA/bar.cu12
-rw-r--r--Tests/Module/CheckIPOSupported-CUDA/foo.cu4
-rw-r--r--Tests/Module/CheckIPOSupported-CUDA/main.cu62
-rw-r--r--Tests/ModuleDefinition/CMakeLists.txt12
-rw-r--r--Tests/Preprocess/CMakeLists.txt7
-rw-r--r--Tests/Preprocess/preprocess.c2
-rw-r--r--Tests/Preprocess/preprocess.cxx2
-rw-r--r--Tests/RunCMake/AutoExportDll/AutoExport.cmake4
-rw-r--r--Tests/RunCMake/BuildDepends/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake4
-rw-r--r--Tests/RunCMake/CMakeLists.txt45
-rw-r--r--Tests/RunCMake/CMakePresets/Comment-stderr.txt9
-rw-r--r--Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt22
-rw-r--r--Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt5
-rw-r--r--Tests/RunCMake/CMakePresets/GoodNoSCache.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt5
-rw-r--r--Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt9
-rw-r--r--Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt8
-rw-r--r--Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in14
-rw-r--r--Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt8
-rw-r--r--Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in14
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsInvalidType-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake6
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake18
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake1
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake7
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake6
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake7
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake7
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake6
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake7
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good.cmake31
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/Good.json.in135
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt4
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/ListPresets.cmake (renamed from Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake)0
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in20
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake102
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in4
-rw-r--r--Tests/RunCMake/CMakePresetsPackage/check.cmake3
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake4
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake4
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good.json.in16
-rw-r--r--Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in17
-rw-r--r--Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in17
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt4
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt17
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake8
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in32
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt (renamed from Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake)0
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in27
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/Fresh.cmake4
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/Fresh.json.in21
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt19
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/Good.cmake8
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/Good.json.in87
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in14
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-result.txt (renamed from Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt6
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt4
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in30
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in9
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in14
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake89
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in25
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in14
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in8
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in4
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in23
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in20
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in20
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/check.cmake3
-rw-r--r--Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in1
-rw-r--r--Tests/RunCMake/CPack/DEB/Helpers.cmake4
-rw-r--r--Tests/RunCMake/CPack/DEB/Prerequirements.cmake6
-rw-r--r--Tests/RunCMake/CPack/RPM/Prerequirements.cmake6
-rw-r--r--Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake2
-rw-r--r--Tests/RunCMake/CTestTimeout/TestTimeout.c1
-rw-r--r--Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake40
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake35
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake12
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI-check.cmake24
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI.cmake23
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake76
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake85
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake59
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20.cmake11
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake12
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt30
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport.cmake16
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt22
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake15
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt17
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/RunCMakeTest.cmake170
-rw-r--r--Tests/RunCMake/CXXModules/check-json.cmake160
-rw-r--r--Tests/RunCMake/CXXModules/compiler_introspection.cmake25
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake27
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake18
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt66
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt56
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt59
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt53
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt56
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt23
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in5
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt27
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake7
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt25
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake4
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt31
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx9
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/library-static-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt30
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt31
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/importable.cxx9
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/partition.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt1
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt18
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json45
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json45
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json73
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json73
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json40
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json40
-rw-r--r--Tests/RunCMake/CXXModules/sources/c-anchor.c4
-rw-r--r--Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx4
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-header.h9
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-impl.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx11
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-internal-part.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-part-impl.cxx13
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-part.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-use.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/sources/module.cxx5
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake38
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake27
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake33
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCUDA.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckCUDACompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake26
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagFortran.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckFortranCompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagHIP.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagISPC.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckISPCCompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJC.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckOBJCCompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJCXX.cmake (renamed from Tests/RunCMake/CheckCompilerFlag/CheckOBJCXXCompilerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake16
-rw-r--r--Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt4
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagC.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCUDA.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckCUDALinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCXX.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagFortran.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagHIP.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJC.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJCXX.cmake (renamed from Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake)0
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake14
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake6
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake10
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake9
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake9
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake15
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCUDA.cmake (renamed from Tests/RunCMake/CheckSourceCompiles/CheckCUDASourceCompiles.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake28
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesFortran.cmake (renamed from Tests/RunCMake/CheckSourceCompiles/CheckFortranSourceCompiles.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesHIP.cmake (renamed from Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesISPC.cmake (renamed from Tests/RunCMake/CheckSourceCompiles/CheckISPCSourceCompiles.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake16
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake19
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake10
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake10
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake9
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake9
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake15
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCUDA.cmake (renamed from Tests/RunCMake/CheckSourceRuns/CheckCUDASourceRuns.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake22
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsFortran.cmake (renamed from Tests/RunCMake/CheckSourceRuns/CheckFortranSourceRuns.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsHIP.cmake (renamed from Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake)0
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake16
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake19
-rw-r--r--Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/ClangTidy/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/ClangTidy/compdb.cmake7
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt5
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake0
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt5
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake0
-rw-r--r--Tests/RunCMake/CommandLine/E_capabilities-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_env-equal.cmake15
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/P_working-dir.cmake7
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake70
-rw-r--r--Tests/RunCMake/CommandLine/cmake_depends-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt11
-rw-r--r--Tests/RunCMake/CommandLine/debug-trycompile.cmake5
-rw-r--r--Tests/RunCMake/CommandLine/trycompile-clean.cmake8
-rw-r--r--Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/C-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/C.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CompilerTest/CUDA-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/CUDA.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/CXX-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/CXX.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/Fortran-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/Fortran.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/HIP-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/HIP.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/ISPC-stdout.txt3
-rw-r--r--Tests/RunCMake/CompilerTest/ISPC.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/OBJC-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/OBJC.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt2
-rw-r--r--Tests/RunCMake/CompilerTest/OBJCXX.cmake3
-rw-r--r--Tests/RunCMake/CompilerTest/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/Configure/CopyFileABI-override.cmake (renamed from Tests/RunCMake/Configure/FailCopyFileABI-override.cmake)3
-rw-r--r--Tests/RunCMake/Configure/CopyFileABI-stdout.txt (renamed from Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt)2
-rw-r--r--Tests/RunCMake/Configure/CopyFileABI.cmake (renamed from Tests/RunCMake/Configure/FailCopyFileABI.cmake)2
-rw-r--r--Tests/RunCMake/Configure/FailCopyFileABI-check.cmake14
-rw-r--r--Tests/RunCMake/Configure/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt6
-rw-r--r--Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt2
-rw-r--r--Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake20
-rw-r--r--Tests/RunCMake/ExternalProject/RunCMakeTest.cmake22
-rw-r--r--Tests/RunCMake/FPHSA/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/FPHSA/empty_version-result.txt1
-rw-r--r--Tests/RunCMake/FPHSA/empty_version-stderr.txt9
-rw-r--r--Tests/RunCMake/FPHSA/empty_version.cmake1
-rw-r--r--Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt1
-rw-r--r--Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake1
-rw-r--r--Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt20
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp0
-rw-r--r--Tests/RunCMake/FetchContent/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/FetchContent/System.cmake37
-rw-r--r--Tests/RunCMake/FileAPI/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/FileAPI/ClientStateful-check.py6
-rw-r--r--Tests/RunCMake/FileAPI/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py12
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json11
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json32
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json6
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json150
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json6
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2.cmake3
-rw-r--r--Tests/RunCMake/FileAPI/subdir/CMakeLists.txt4
-rw-r--r--Tests/RunCMake/FileAPI/subdir/empty.c0
-rw-r--r--Tests/RunCMake/File_Archive/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args-result.txt1
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args-stderr.txt19
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args.cmake8
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args-result.txt1
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt11
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args.cmake5
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-check.cmake8
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-input.txt1
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent.cmake10
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/Framework/FrameworkConsumption.cmake18
-rw-r--r--Tests/RunCMake/Framework/main2.c9
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt1
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt5
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake2
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake4
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake2
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake2
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake31
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx0
-rw-r--r--Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake17
-rw-r--r--Tests/RunCMake/Ninja/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-54936-check.cmake3
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-54936-stdout.txt1
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-54936.cmake2
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-65001-check.cmake3
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-65001-stdout.txt1
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-65001.cmake2
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-check.cmake17
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes-cmake.cmake7
-rw-r--r--Tests/RunCMake/Ninja/ShowIncludes.cmake22
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake28
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake1
-rw-r--r--Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchDebugGenex.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake4
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake4
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchInterface.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake4
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake5
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake4
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake2
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake2
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFrom-common.cmake (renamed from Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake)3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake5
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake3
-rw-r--r--Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake5
-rw-r--r--Tests/RunCMake/RunCMake.cmake11
-rw-r--r--Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt1
-rw-r--r--Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake46
-rw-r--r--Tests/RunCMake/VS10Project/DebugInformationFormat.cmake24
-rw-r--r--Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake9
-rw-r--r--Tests/RunCMake/VS10Project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake2
-rw-r--r--Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VsDotnetSdk/VsDotnetSdk.cmake10
-rw-r--r--Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake64
-rw-r--r--Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake19
-rw-r--r--Tests/RunCMake/XcodeProject/Clean-build-check.cmake5
-rw-r--r--Tests/RunCMake/XcodeProject/Clean-clean-check.cmake5
-rw-r--r--Tests/RunCMake/XcodeProject/Clean.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/XcodeProject/Clean/empty.c0
-rw-r--r--Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake12
-rw-r--r--Tests/RunCMake/XcodeProject/RunCMakeTest.cmake27
-rw-r--r--Tests/RunCMake/XcodeProject/SearchPaths-check.cmake14
-rw-r--r--Tests/RunCMake/XcodeProject/SearchPaths.cmake10
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake4
-rw-r--r--Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/add_subdirectory/System.cmake22
-rw-r--r--Tests/RunCMake/add_subdirectory/System/CMakeLists.txt11
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/bar.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/foo.cpp0
-rw-r--r--Tests/RunCMake/add_subdirectory/System/zot.cpp0
-rw-r--r--Tests/RunCMake/block/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/block/EndAlone-result.txt1
-rw-r--r--Tests/RunCMake/block/EndAlone-stderr.txt4
-rw-r--r--Tests/RunCMake/block/EndAlone.cmake1
-rw-r--r--Tests/RunCMake/block/EndAloneWithArgument-result.txt1
-rw-r--r--Tests/RunCMake/block/EndAloneWithArgument-stderr.txt4
-rw-r--r--Tests/RunCMake/block/EndAloneWithArgument.cmake1
-rw-r--r--Tests/RunCMake/block/EndMissing-result.txt1
-rw-r--r--Tests/RunCMake/block/EndMissing-stderr.txt4
-rw-r--r--Tests/RunCMake/block/EndMissing.cmake1
-rw-r--r--Tests/RunCMake/block/EndWithArgument-stderr.txt9
-rw-r--r--Tests/RunCMake/block/EndWithArgument.cmake2
-rw-r--r--Tests/RunCMake/block/InvalidArgument-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidArgument-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidArgument.cmake2
-rw-r--r--Tests/RunCMake/block/InvalidNesting1-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting1-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting1.cmake6
-rw-r--r--Tests/RunCMake/block/InvalidNesting2-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting2-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting2.cmake6
-rw-r--r--Tests/RunCMake/block/InvalidNesting3-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting3-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting3.cmake5
-rw-r--r--Tests/RunCMake/block/InvalidNesting4-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting4-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting4.cmake5
-rw-r--r--Tests/RunCMake/block/InvalidNesting5-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting5-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting5.cmake5
-rw-r--r--Tests/RunCMake/block/InvalidNesting6-result.txt1
-rw-r--r--Tests/RunCMake/block/InvalidNesting6-stderr.txt4
-rw-r--r--Tests/RunCMake/block/InvalidNesting6.cmake5
-rw-r--r--Tests/RunCMake/block/MissingArgument-result.txt1
-rw-r--r--Tests/RunCMake/block/MissingArgument-stderr.txt7
-rw-r--r--Tests/RunCMake/block/MissingArgument.cmake2
-rw-r--r--Tests/RunCMake/block/RunCMakeTest.cmake22
-rw-r--r--Tests/RunCMake/block/Scope-POLICIES.cmake40
-rw-r--r--Tests/RunCMake/block/Scope-VARIABLES.cmake62
-rw-r--r--Tests/RunCMake/block/Scope.cmake62
-rw-r--r--Tests/RunCMake/block/Scope/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/block/Workflows.cmake78
-rw-r--r--Tests/RunCMake/block/WrongArgument-result.txt1
-rw-r--r--Tests/RunCMake/block/WrongArgument-stderr.txt4
-rw-r--r--Tests/RunCMake/block/WrongArgument.cmake2
-rw-r--r--Tests/RunCMake/block/WrongScope-result.txt1
-rw-r--r--Tests/RunCMake/block/WrongScope-stderr.txt4
-rw-r--r--Tests/RunCMake/block/WrongScope.cmake2
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt6
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt6
-rw-r--r--Tests/RunCMake/cmake_language/RunCMakeTest.cmake60
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level.cmake5
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_path/RunCMakeTest.cmake11
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake9
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake9
-rw-r--r--Tests/RunCMake/ctest_environment/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake9
-rw-r--r--Tests/RunCMake/execute_process/EchoCommand3-stderr.txt4
-rw-r--r--Tests/RunCMake/execute_process/EncodingMissing-stderr.txt5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake6
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt6
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake4
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt4
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt4
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt4
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake5
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-override.cmake6
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt6
-rw-r--r--Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake6
-rw-r--r--Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/file-CHMOD/all-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/all-perms-stderr.txt4
-rw-r--r--Tests/RunCMake/file-CHMOD/all-perms.cmake3
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-path-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt6
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-path.cmake1
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt3
-rw-r--r--Tests/RunCMake/file-CHMOD/invalid-perms.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt5
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt5
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-file-perms.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt5
-rw-r--r--Tests/RunCMake/file-CHMOD/missing-perms.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/no-perms-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/no-perms-stderr.txt3
-rw-r--r--Tests/RunCMake/file-CHMOD/no-perms.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/ok.cmake2
-rw-r--r--Tests/RunCMake/file-CHMOD/override.cmake3
-rw-r--r--Tests/RunCMake/file-CHMOD/write-only-result.txt1
-rw-r--r--Tests/RunCMake/file-CHMOD/write-only-stderr.txt6
-rw-r--r--Tests/RunCMake/file-CHMOD/write-only.cmake3
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt20
-rw-r--r--Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt9
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/file/TIMESTAMP-stdout.txt1
-rw-r--r--Tests/RunCMake/file/TIMESTAMP.cmake2
-rw-r--r--Tests/RunCMake/find_file/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/find_library/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR.cmake41
-rw-r--r--Tests/RunCMake/find_package/RunCMakeTest.cmake16
-rw-r--r--Tests/RunCMake/find_package/SearchPaths.cmake2
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake0
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt10
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt14
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake1
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake1
-rw-r--r--Tests/RunCMake/find_path/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/find_program/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt1
-rw-r--r--Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt12
-rw-r--r--Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt12
-rw-r--r--Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake11
-rw-r--r--Tests/RunCMake/install/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/project/LanguagesDuplicate-check.cmake10
-rw-r--r--Tests/RunCMake/project/LanguagesDuplicate.cmake11
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/pseudo_tidy.c10
-rw-r--r--Tests/RunCMake/return/CMP0140-NEW.cmake13
-rw-r--r--Tests/RunCMake/return/CMP0140-OLD.cmake8
-rw-r--r--Tests/RunCMake/return/CMP0140-WARN-result.txt1
-rw-r--r--Tests/RunCMake/return/CMP0140-WARN-stderr.txt12
-rw-r--r--Tests/RunCMake/return/CMP0140-WARN.cmake8
-rw-r--r--Tests/RunCMake/return/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/return/PropagateFromDirectory.cmake10
-rw-r--r--Tests/RunCMake/return/PropagateFromFunction.cmake142
-rw-r--r--Tests/RunCMake/return/PropagateNothing.cmake2
-rw-r--r--Tests/RunCMake/return/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/return/WrongArgument-result.txt1
-rw-r--r--Tests/RunCMake/return/WrongArgument-stderr.txt4
-rw-r--r--Tests/RunCMake/return/WrongArgument.cmake2
-rw-r--r--Tests/RunCMake/return/subdir/CMakeLists.txt5
-rw-r--r--Tests/RunCMake/showIncludes.c33
-rw-r--r--Tests/RunCMake/string/JSON.cmake6
-rw-r--r--Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt10
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake30
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt1
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt12
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake6
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt1
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt12
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake6
-rw-r--r--Tests/RunCMake/target_sources/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/BadLinkLibraries.cmake6
-rw-r--r--Tests/RunCMake/try_compile/BadSources1-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/BadSources1.cmake4
-rw-r--r--Tests/RunCMake/try_compile/BadSources2-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/BadSources2.cmake7
-rw-r--r--Tests/RunCMake/try_compile/BinDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/BinDirEmpty.cmake1
-rw-r--r--Tests/RunCMake/try_compile/BinDirRelative-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/BinDirRelative-stderr.txt6
-rw-r--r--Tests/RunCMake/try_compile/BinDirRelative.cmake1
-rw-r--r--Tests/RunCMake/try_compile/BuildType.cmake8
-rw-r--r--Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake9
-rw-r--r--Tests/RunCMake/try_compile/CStandard-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/CStandard.cmake8
-rw-r--r--Tests/RunCMake/try_compile/CStandardGNU.cmake15
-rw-r--r--Tests/RunCMake/try_compile/CStandardNoDefault.cmake8
-rw-r--r--Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake4
-rw-r--r--Tests/RunCMake/try_compile/CudaStandard-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/CudaStandard.cmake8
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard-stderr.txt15
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard.cmake8
-rw-r--r--Tests/RunCMake/try_compile/CxxStandardGNU.cmake15
-rw-r--r--Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake8
-rw-r--r--Tests/RunCMake/try_compile/EmptyListArgs.cmake11
-rw-r--r--Tests/RunCMake/try_compile/EmptyValueArgs-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt9
-rw-r--r--Tests/RunCMake/try_compile/EmptyValueArgs.cmake7
-rw-r--r--Tests/RunCMake/try_compile/EnvConfig.cmake6
-rw-r--r--Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake12
-rw-r--r--Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake13
-rw-r--r--Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake9
-rw-r--r--Tests/RunCMake/try_compile/ISPCTargets.cmake9
-rw-r--r--Tests/RunCMake/try_compile/NoArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile2.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFileError.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable2.cmake4
-rw-r--r--Tests/RunCMake/try_compile/NoSources-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/ObjCStandard-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/ObjCStandard.cmake8
-rw-r--r--Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/ObjCxxStandard.cmake8
-rw-r--r--Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake1
-rw-r--r--Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake1
-rw-r--r--Tests/RunCMake/try_compile/OneArg-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/OutputDirAsFlag.cmake9
-rw-r--r--Tests/RunCMake/try_compile/PlatformVariables-stderr.txt11
-rw-r--r--Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake4
-rw-r--r--Tests/RunCMake/try_compile/ProjectCopyFile-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/ProjectCopyFile.cmake4
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake1
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake1
-rw-r--r--Tests/RunCMake/try_compile/RunCMakeTest.cmake72
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile.cmake1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadName-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadName.cmake1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromOneArg-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/SourceFromOneArg.cmake1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake1
-rw-r--r--Tests/RunCMake/try_compile/TargetTypeExe.cmake10
-rw-r--r--Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt2
-rw-r--r--Tests/RunCMake/try_compile/TargetTypeInvalid.cmake6
-rw-r--r--Tests/RunCMake/try_compile/TargetTypeStatic.cmake10
-rw-r--r--Tests/RunCMake/try_compile/TryRunArgs-stderr.txt18
-rw-r--r--Tests/RunCMake/try_compile/TryRunArgs.cmake14
-rw-r--r--Tests/RunCMake/try_compile/TwoArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt11
-rw-r--r--Tests/RunCMake/try_compile/new_signature.cmake2
-rw-r--r--Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake66
-rw-r--r--Tests/RunCMake/try_compile/old_signature.cmake2
-rw-r--r--Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt2
-rw-r--r--Tests/RunCMake/try_run/BadLinkLibraries.cmake7
-rw-r--r--Tests/RunCMake/try_run/BinDirEmpty-result.txt1
-rw-r--r--Tests/RunCMake/try_run/BinDirEmpty-stderr.txt4
-rw-r--r--Tests/RunCMake/try_run/BinDirEmpty.cmake1
-rw-r--r--Tests/RunCMake/try_run/BinDirRelative-result.txt1
-rw-r--r--Tests/RunCMake/try_run/BinDirRelative-stderr.txt6
-rw-r--r--Tests/RunCMake/try_run/BinDirRelative.cmake1
-rw-r--r--Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoCompileOutputVariable.cmake6
-rw-r--r--Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoOutputVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoOutputVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoOutputVariable.cmake4
-rw-r--r--Tests/RunCMake/try_run/NoRunOutputVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoRunOutputVariable.cmake6
-rw-r--r--Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoRunStdErrVariable.cmake7
-rw-r--r--Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoRunStdOutVariable.cmake7
-rw-r--r--Tests/RunCMake/try_run/NoWorkingDirectory-result.txt1
-rw-r--r--Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt7
-rw-r--r--Tests/RunCMake/try_run/NoWorkingDirectory.cmake6
-rw-r--r--Tests/RunCMake/try_run/RunCMakeTest.cmake14
-rw-r--r--Tests/RunCMake/try_run/WorkingDirArg.cmake8
-rw-r--r--Tests/RunCMake/try_run/new_signature.cmake2
-rw-r--r--Tests/RunCMake/try_run/old_and_new_signature_tests.cmake20
-rw-r--r--Tests/RunCMake/try_run/old_signature.cmake2
-rw-r--r--Tests/SwiftMix/CMain.c13
-rw-r--r--Tests/SwiftMix/CMakeLists.txt1
-rw-r--r--Tests/SwiftMix/SwiftMain.swift20
-rw-r--r--Tests/SwiftMixLib/CMakeLists.txt6
-rw-r--r--Tests/SwiftMixLib/lib.c4
-rw-r--r--Tests/SwiftMixLib/lib.cpp4
-rw-r--r--Tests/SwiftMixLib/lib.swift3
-rw-r--r--Tests/SwiftMixLib/main.swift3
-rw-r--r--Tests/SwiftOnly/CMakeLists.txt4
-rw-r--r--Tests/SwiftOnly/SubA/CMakeLists.txt2
-rw-r--r--Tests/SwiftOnly/SubA/SubA.swift0
-rw-r--r--Tests/SwiftOnly/SubB/CMakeLists.txt2
-rw-r--r--Tests/SwiftOnly/SubB/SubB.swift1
-rw-r--r--Tests/SwiftOnly/main.swift6
-rw-r--r--Tests/TryCompile/CMakeLists.txt457
-rw-r--r--Tests/TryCompile/exit_with_error.c2
-rw-r--r--Tests/TryCompile/old_and_new_signature_tests.cmake276
-rw-r--r--Tests/TryCompile/stdout_and_stderr.c8
-rw-r--r--Tests/VSGNUFortran/CMakeLists.txt2
-rw-r--r--Tests/VSWinStorePhone/VerifyAppPackage.cmake2
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/IWYU/mapping.imp2
-rw-r--r--Utilities/Release/WiX/CustomAction/CMakeLists.txt4
-rw-r--r--Utilities/Release/linux/aarch64/Dockerfile2
-rw-r--r--Utilities/Release/linux/x86_64/Dockerfile2
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-libuv.bash2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt18
-rw-r--r--Utilities/Sphinx/cmake.py18
-rw-r--r--Utilities/Sphinx/static/cmake.css11
-rw-r--r--Utilities/cmThirdPartyChecks.cmake8
-rw-r--r--Utilities/cmcurl/CMake/CMakeConfigurableFile.in4
-rw-r--r--Utilities/cmcurl/CMake/CurlSymbolHiding.cmake4
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c60
-rw-r--r--Utilities/cmcurl/CMake/FindBearSSL.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindBrotli.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindCARES.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindGSS.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindLibPSL.cmake45
-rw-r--r--Utilities/cmcurl/CMake/FindLibSSH2.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindMSH3.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindMbedTLS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP2.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP3.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindNGTCP2.cmake6
-rw-r--r--Utilities/cmcurl/CMake/FindNSS.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindQUICHE.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindWolfSSL.cmake4
-rw-r--r--Utilities/cmcurl/CMake/FindZstd.cmake4
-rw-r--r--Utilities/cmcurl/CMake/Macros.cmake4
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake171
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake41
-rw-r--r--Utilities/cmcurl/CMake/Utilities.cmake4
-rw-r--r--Utilities/cmcurl/CMake/cmake_uninstall.cmake.in4
-rw-r--r--Utilities/cmcurl/CMake/curl-config.cmake.in4
-rw-r--r--Utilities/cmcurl/CMakeLists.txt328
-rw-r--r--Utilities/cmcurl/include/curl/curl.h77
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h10
-rw-r--r--Utilities/cmcurl/include/curl/easy.h4
-rw-r--r--Utilities/cmcurl/include/curl/header.h10
-rw-r--r--Utilities/cmcurl/include/curl/mprintf.h4
-rw-r--r--Utilities/cmcurl/include/curl/multi.h7
-rw-r--r--Utilities/cmcurl/include/curl/options.h4
-rw-r--r--Utilities/cmcurl/include/curl/stdcheaders.h4
-rw-r--r--Utilities/cmcurl/include/curl/system.h2
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h17
-rw-r--r--Utilities/cmcurl/include/curl/urlapi.h4
-rw-r--r--Utilities/cmcurl/include/curl/websockets.h83
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt30
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc17
-rw-r--r--Utilities/cmcurl/lib/altsvc.c62
-rw-r--r--Utilities/cmcurl/lib/altsvc.h4
-rw-r--r--Utilities/cmcurl/lib/amigaos.c212
-rw-r--r--Utilities/cmcurl/lib/amigaos.h18
-rw-r--r--Utilities/cmcurl/lib/arpa_telnet.h4
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c49
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c21
-rw-r--r--Utilities/cmcurl/lib/asyn.h6
-rw-r--r--Utilities/cmcurl/lib/base64.c80
-rw-r--r--Utilities/cmcurl/lib/bufref.c4
-rw-r--r--Utilities/cmcurl/lib/bufref.h4
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c69
-rw-r--r--Utilities/cmcurl/lib/c-hyper.h5
-rw-r--r--Utilities/cmcurl/lib/conncache.c4
-rw-r--r--Utilities/cmcurl/lib/conncache.h3
-rw-r--r--Utilities/cmcurl/lib/connect.c85
-rw-r--r--Utilities/cmcurl/lib/connect.h4
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c85
-rw-r--r--Utilities/cmcurl/lib/content_encoding.h7
-rw-r--r--Utilities/cmcurl/lib/cookie.c204
-rw-r--r--Utilities/cmcurl/lib/cookie.h25
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c6
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.h4
-rw-r--r--Utilities/cmcurl/lib/curl_base64.h2
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake260
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.c130
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.h42
-rw-r--r--Utilities/cmcurl/lib/curl_des.c4
-rw-r--r--Utilities/cmcurl/lib/curl_des.h2
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c4
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.h4
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.c10
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.h4
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.c4
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.h4
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c14
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_hmac.h6
-rw-r--r--Utilities/cmcurl/lib/curl_krb5.h4
-rw-r--r--Utilities/cmcurl/lib/curl_ldap.h4
-rw-r--r--Utilities/cmcurl/lib/curl_md4.h4
-rw-r--r--Utilities/cmcurl/lib/curl_md5.h4
-rw-r--r--Utilities/cmcurl/lib/curl_memory.h4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.c4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.h4
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.c2
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.h4
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c17
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.h6
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c6
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.h4
-rw-r--r--Utilities/cmcurl/lib/curl_path.c5
-rw-r--r--Utilities/cmcurl/lib/curl_path.h4
-rw-r--r--Utilities/cmcurl/lib/curl_printf.h4
-rw-r--r--Utilities/cmcurl/lib/curl_range.c6
-rw-r--r--Utilities/cmcurl/lib/curl_range.h4
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c6
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.h4
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c2
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.h2
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h58
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h79
-rw-r--r--Utilities/cmcurl/lib/curl_sha256.h3
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_threads.c4
-rw-r--r--Utilities/cmcurl/lib/curl_threads.h4
-rw-r--r--Utilities/cmcurl/lib/curlx.h4
-rw-r--r--Utilities/cmcurl/lib/dict.c2
-rw-r--r--Utilities/cmcurl/lib/dict.h4
-rw-r--r--Utilities/cmcurl/lib/doh.c21
-rw-r--r--Utilities/cmcurl/lib/doh.h51
-rw-r--r--Utilities/cmcurl/lib/dotdot.c182
-rw-r--r--Utilities/cmcurl/lib/dynbuf.c21
-rw-r--r--Utilities/cmcurl/lib/dynbuf.h10
-rw-r--r--Utilities/cmcurl/lib/easy.c136
-rw-r--r--Utilities/cmcurl/lib/easy_lock.h105
-rw-r--r--Utilities/cmcurl/lib/easygetopt.c4
-rw-r--r--Utilities/cmcurl/lib/easyif.h7
-rw-r--r--Utilities/cmcurl/lib/easyoptions.c20
-rw-r--r--Utilities/cmcurl/lib/easyoptions.h4
-rw-r--r--Utilities/cmcurl/lib/escape.c8
-rw-r--r--Utilities/cmcurl/lib/escape.h2
-rw-r--r--Utilities/cmcurl/lib/file.c31
-rw-r--r--Utilities/cmcurl/lib/file.h4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h4
-rw-r--r--Utilities/cmcurl/lib/fopen.c113
-rw-r--r--Utilities/cmcurl/lib/fopen.h (renamed from Utilities/cmcurl/lib/vssh/wolfssh.h)13
-rw-r--r--Utilities/cmcurl/lib/formdata.c8
-rw-r--r--Utilities/cmcurl/lib/formdata.h4
-rw-r--r--Utilities/cmcurl/lib/ftp.c42
-rw-r--r--Utilities/cmcurl/lib/ftp.h7
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c8
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.h4
-rw-r--r--Utilities/cmcurl/lib/functypes.h115
-rw-r--r--Utilities/cmcurl/lib/getenv.c4
-rw-r--r--Utilities/cmcurl/lib/getinfo.c22
-rw-r--r--Utilities/cmcurl/lib/getinfo.h4
-rw-r--r--Utilities/cmcurl/lib/gopher.c2
-rw-r--r--Utilities/cmcurl/lib/gopher.h4
-rw-r--r--Utilities/cmcurl/lib/h2h3.c7
-rw-r--r--Utilities/cmcurl/lib/h2h3.h2
-rw-r--r--Utilities/cmcurl/lib/hash.c4
-rw-r--r--Utilities/cmcurl/lib/hash.h4
-rw-r--r--Utilities/cmcurl/lib/headers.c72
-rw-r--r--Utilities/cmcurl/lib/headers.h4
-rw-r--r--Utilities/cmcurl/lib/hmac.c2
-rw-r--r--Utilities/cmcurl/lib/hostasyn.c4
-rw-r--r--Utilities/cmcurl/lib/hostip.c75
-rw-r--r--Utilities/cmcurl/lib/hostip.h6
-rw-r--r--Utilities/cmcurl/lib/hostip4.c10
-rw-r--r--Utilities/cmcurl/lib/hostip6.c10
-rw-r--r--Utilities/cmcurl/lib/hostsyn.c4
-rw-r--r--Utilities/cmcurl/lib/hsts.c33
-rw-r--r--Utilities/cmcurl/lib/hsts.h4
-rw-r--r--Utilities/cmcurl/lib/http.c201
-rw-r--r--Utilities/cmcurl/lib/http.h27
-rw-r--r--Utilities/cmcurl/lib/http2.c67
-rw-r--r--Utilities/cmcurl/lib/http2.h4
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.c542
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.h4
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c7
-rw-r--r--Utilities/cmcurl/lib/http_chunks.h4
-rw-r--r--Utilities/cmcurl/lib/http_digest.c8
-rw-r--r--Utilities/cmcurl/lib/http_digest.h4
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c4
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.h4
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c4
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.h4
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c12
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h2
-rw-r--r--Utilities/cmcurl/lib/idn_win32.c10
-rw-r--r--Utilities/cmcurl/lib/if2ip.c2
-rw-r--r--Utilities/cmcurl/lib/if2ip.h2
-rw-r--r--Utilities/cmcurl/lib/imap.c20
-rw-r--r--Utilities/cmcurl/lib/imap.h4
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.c4
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.h4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.c4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.h4
-rw-r--r--Utilities/cmcurl/lib/krb5.c20
-rw-r--r--Utilities/cmcurl/lib/ldap.c28
-rw-r--r--Utilities/cmcurl/lib/libcurl.rc4
-rw-r--r--Utilities/cmcurl/lib/llist.c4
-rw-r--r--Utilities/cmcurl/lib/llist.h4
-rw-r--r--Utilities/cmcurl/lib/md4.c15
-rw-r--r--Utilities/cmcurl/lib/md5.c4
-rw-r--r--Utilities/cmcurl/lib/memdebug.c25
-rw-r--r--Utilities/cmcurl/lib/memdebug.h49
-rw-r--r--Utilities/cmcurl/lib/mime.c11
-rw-r--r--Utilities/cmcurl/lib/mime.h7
-rw-r--r--Utilities/cmcurl/lib/mprintf.c35
-rw-r--r--Utilities/cmcurl/lib/mqtt.c28
-rw-r--r--Utilities/cmcurl/lib/mqtt.h4
-rw-r--r--Utilities/cmcurl/lib/multi.c90
-rw-r--r--Utilities/cmcurl/lib/multihandle.h14
-rw-r--r--Utilities/cmcurl/lib/multiif.h7
-rw-r--r--Utilities/cmcurl/lib/netrc.c124
-rw-r--r--Utilities/cmcurl/lib/netrc.h12
-rw-r--r--Utilities/cmcurl/lib/nonblock.c2
-rw-r--r--Utilities/cmcurl/lib/nonblock.h4
-rw-r--r--Utilities/cmcurl/lib/noproxy.c222
-rw-r--r--Utilities/cmcurl/lib/noproxy.h (renamed from Utilities/cmcurl/lib/dotdot.h)29
-rw-r--r--Utilities/cmcurl/lib/openldap.c6
-rw-r--r--Utilities/cmcurl/lib/parsedate.c4
-rw-r--r--Utilities/cmcurl/lib/parsedate.h4
-rw-r--r--Utilities/cmcurl/lib/pingpong.c7
-rw-r--r--Utilities/cmcurl/lib/pingpong.h4
-rw-r--r--Utilities/cmcurl/lib/pop3.c2
-rw-r--r--Utilities/cmcurl/lib/pop3.h4
-rw-r--r--Utilities/cmcurl/lib/progress.c4
-rw-r--r--Utilities/cmcurl/lib/progress.h4
-rw-r--r--Utilities/cmcurl/lib/psl.c4
-rw-r--r--Utilities/cmcurl/lib/psl.h4
-rw-r--r--Utilities/cmcurl/lib/quic.h3
-rw-r--r--Utilities/cmcurl/lib/rand.c77
-rw-r--r--Utilities/cmcurl/lib/rand.h12
-rw-r--r--Utilities/cmcurl/lib/rename.c4
-rw-r--r--Utilities/cmcurl/lib/rename.h4
-rw-r--r--Utilities/cmcurl/lib/rtsp.c4
-rw-r--r--Utilities/cmcurl/lib/rtsp.h4
-rw-r--r--Utilities/cmcurl/lib/select.c14
-rw-r--r--Utilities/cmcurl/lib/select.h5
-rw-r--r--Utilities/cmcurl/lib/sendf.c75
-rw-r--r--Utilities/cmcurl/lib/sendf.h6
-rw-r--r--Utilities/cmcurl/lib/setopt.c245
-rw-r--r--Utilities/cmcurl/lib/setopt.h4
-rw-r--r--Utilities/cmcurl/lib/setup-os400.h4
-rw-r--r--Utilities/cmcurl/lib/setup-vms.h4
-rw-r--r--Utilities/cmcurl/lib/setup-win32.h19
-rw-r--r--Utilities/cmcurl/lib/sha256.c2
-rw-r--r--Utilities/cmcurl/lib/share.c6
-rw-r--r--Utilities/cmcurl/lib/share.h4
-rw-r--r--Utilities/cmcurl/lib/sigpipe.h4
-rw-r--r--Utilities/cmcurl/lib/slist.c4
-rw-r--r--Utilities/cmcurl/lib/slist.h4
-rw-r--r--Utilities/cmcurl/lib/smb.c4
-rw-r--r--Utilities/cmcurl/lib/smb.h6
-rw-r--r--Utilities/cmcurl/lib/smtp.c10
-rw-r--r--Utilities/cmcurl/lib/smtp.h8
-rw-r--r--Utilities/cmcurl/lib/sockaddr.h4
-rw-r--r--Utilities/cmcurl/lib/socketpair.c4
-rw-r--r--Utilities/cmcurl/lib/socketpair.h6
-rw-r--r--Utilities/cmcurl/lib/socks.c2
-rw-r--r--Utilities/cmcurl/lib/socks.h2
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c8
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c6
-rw-r--r--Utilities/cmcurl/lib/speedcheck.c4
-rw-r--r--Utilities/cmcurl/lib/speedcheck.h4
-rw-r--r--Utilities/cmcurl/lib/splay.c8
-rw-r--r--Utilities/cmcurl/lib/splay.h4
-rw-r--r--Utilities/cmcurl/lib/strcase.c86
-rw-r--r--Utilities/cmcurl/lib/strcase.h4
-rw-r--r--Utilities/cmcurl/lib/strdup.c4
-rw-r--r--Utilities/cmcurl/lib/strdup.h4
-rw-r--r--Utilities/cmcurl/lib/strerror.c16
-rw-r--r--Utilities/cmcurl/lib/strerror.h4
-rw-r--r--Utilities/cmcurl/lib/strtok.c4
-rw-r--r--Utilities/cmcurl/lib/strtok.h4
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c10
-rw-r--r--Utilities/cmcurl/lib/strtoofft.h4
-rw-r--r--Utilities/cmcurl/lib/system_win32.c4
-rw-r--r--Utilities/cmcurl/lib/system_win32.h4
-rw-r--r--Utilities/cmcurl/lib/telnet.c2
-rw-r--r--Utilities/cmcurl/lib/telnet.h4
-rw-r--r--Utilities/cmcurl/lib/tftp.c2
-rw-r--r--Utilities/cmcurl/lib/tftp.h4
-rw-r--r--Utilities/cmcurl/lib/timediff.c4
-rw-r--r--Utilities/cmcurl/lib/timediff.h2
-rw-r--r--Utilities/cmcurl/lib/timeval.c4
-rw-r--r--Utilities/cmcurl/lib/timeval.h2
-rw-r--r--Utilities/cmcurl/lib/transfer.c112
-rw-r--r--Utilities/cmcurl/lib/transfer.h2
-rw-r--r--Utilities/cmcurl/lib/url.c740
-rw-r--r--Utilities/cmcurl/lib/url.h5
-rw-r--r--Utilities/cmcurl/lib/urlapi-int.h10
-rw-r--r--Utilities/cmcurl/lib/urlapi.c904
-rw-r--r--Utilities/cmcurl/lib/urldata.h298
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/cram.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c185
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.h13
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c16
-rw-r--r--Utilities/cmcurl/lib/vauth/gsasl.c7
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c17
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.h7
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/oauth2.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c21
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h10
-rw-r--r--Utilities/cmcurl/lib/version.c21
-rw-r--r--Utilities/cmcurl/lib/version_win32.c2
-rw-r--r--Utilities/cmcurl/lib/version_win32.h4
-rw-r--r--Utilities/cmcurl/lib/vquic/msh3.c58
-rw-r--r--Utilities/cmcurl/lib/vquic/msh3.h2
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c855
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.h36
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.c68
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.h4
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.c2
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.h2
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c60
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c127
-rw-r--r--Utilities/cmcurl/lib/vssh/ssh.h12
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c34
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c11
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/hostcheck.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/hostcheck.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.c5
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c8
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c32
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c840
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h5
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c8
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c518
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h94
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c28
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h7
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c26
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/x509asn1.c7
-rw-r--r--Utilities/cmcurl/lib/vtls/x509asn1.h2
-rw-r--r--Utilities/cmcurl/lib/warnless.c4
-rw-r--r--Utilities/cmcurl/lib/warnless.h2
-rw-r--r--Utilities/cmcurl/lib/wildcard.c4
-rw-r--r--Utilities/cmcurl/lib/wildcard.h5
-rw-r--r--Utilities/cmcurl/lib/ws.c757
-rw-r--r--Utilities/cmcurl/lib/ws.h69
-rw-r--r--Utilities/cmexpat/CMakeLists.txt6
-rw-r--r--Utilities/cmjsoncpp/CMakeLists.txt2
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt2
-rw-r--r--Utilities/cmlibuv/include/uv.h5
-rw-r--r--Utilities/cmlibuv/include/uv/version.h8
-rw-r--r--Utilities/cmlibuv/include/uv/win.h8
-rw-r--r--Utilities/cmlibuv/src/fs-poll.c2
-rw-r--r--Utilities/cmlibuv/src/idna.c11
-rw-r--r--Utilities/cmlibuv/src/strscpy.h2
-rw-r--r--Utilities/cmlibuv/src/strtok.c52
-rw-r--r--Utilities/cmlibuv/src/strtok.h27
-rw-r--r--Utilities/cmlibuv/src/unix/atomic-ops.h15
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-ifaddrs.c8
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-proctitle.c1
-rw-r--r--Utilities/cmlibuv/src/unix/cmake-bootstrap.c2
-rw-r--r--Utilities/cmlibuv/src/unix/core.c244
-rw-r--r--Utilities/cmlibuv/src/unix/freebsd.c15
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c18
-rw-r--r--Utilities/cmlibuv/src/unix/hurd.c167
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h25
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c23
-rw-r--r--Utilities/cmlibuv/src/unix/linux-core.c29
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c36
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c289
-rw-r--r--Utilities/cmlibuv/src/unix/pipe.c8
-rw-r--r--Utilities/cmlibuv/src/unix/process.c786
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c99
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c36
-rw-r--r--Utilities/cmlibuv/src/unix/tcp.c19
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c86
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c84
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c28
-rw-r--r--Utilities/cmlibuv/src/uv-common.c4
-rw-r--r--Utilities/cmlibuv/src/uv-common.h5
-rw-r--r--Utilities/cmlibuv/src/win/async.c10
-rw-r--r--Utilities/cmlibuv/src/win/core.c90
-rw-r--r--Utilities/cmlibuv/src/win/fs-event.c36
-rw-r--r--Utilities/cmlibuv/src/win/fs.c24
-rw-r--r--Utilities/cmlibuv/src/win/handle-inl.h26
-rw-r--r--Utilities/cmlibuv/src/win/handle.c26
-rw-r--r--Utilities/cmlibuv/src/win/internal.h145
-rw-r--r--Utilities/cmlibuv/src/win/loop-watcher.c4
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c556
-rw-r--r--Utilities/cmlibuv/src/win/poll.c36
-rw-r--r--Utilities/cmlibuv/src/win/process.c20
-rw-r--r--Utilities/cmlibuv/src/win/req-inl.h43
-rw-r--r--Utilities/cmlibuv/src/win/signal.c12
-rw-r--r--Utilities/cmlibuv/src/win/stream-inl.h8
-rw-r--r--Utilities/cmlibuv/src/win/stream.c31
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c255
-rw-r--r--Utilities/cmlibuv/src/win/thread.c3
-rw-r--r--Utilities/cmlibuv/src/win/tty.c221
-rw-r--r--Utilities/cmlibuv/src/win/udp.c103
-rw-r--r--Utilities/cmlibuv/src/win/util.c106
-rw-r--r--Utilities/cmlibuv/src/win/winapi.c8
-rw-r--r--Utilities/cmlibuv/src/win/winsock.c28
-rw-r--r--Utilities/std/cmext/enum_set13
-rwxr-xr-xbootstrap8
2039 files changed, 37645 insertions, 14635 deletions
diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el
index 8224d9e0b..a11becbe2 100644
--- a/Auxiliary/cmake-mode.el
+++ b/Auxiliary/cmake-mode.el
@@ -41,8 +41,8 @@ set the path with these commands:
:group 'cmake)
;; Keywords
-(defconst cmake-keywords-block-open '("IF" "MACRO" "FOREACH" "ELSE" "ELSEIF" "WHILE" "FUNCTION"))
-(defconst cmake-keywords-block-close '("ENDIF" "ENDFOREACH" "ENDMACRO" "ELSE" "ELSEIF" "ENDWHILE" "ENDFUNCTION"))
+(defconst cmake-keywords-block-open '("BLOCK" "IF" "MACRO" "FOREACH" "ELSE" "ELSEIF" "WHILE" "FUNCTION"))
+(defconst cmake-keywords-block-close '("ENDBLOCK" "ENDIF" "ENDFOREACH" "ENDMACRO" "ELSE" "ELSEIF" "ENDWHILE" "ENDFUNCTION"))
(defconst cmake-keywords
(let ((kwds (append cmake-keywords-block-open cmake-keywords-block-close nil)))
(delete-dups kwds)))
@@ -288,6 +288,39 @@ This puts the mark at the end, and point at the beginning."
;------------------------------------------------------------------------------
+(defun cmake--syntax-propertize-until-bracket-close (syntax)
+ ;; This function assumes that a previous search has matched the
+ ;; beginning of a bracket_comment or bracket_argument and that the
+ ;; second capture group has matched the equal signs between the two
+ ;; opening brackets
+ (let* ((mb (match-beginning 2))
+ (me (match-end 2))
+ (cb (format "]%s]" (buffer-substring mb me))))
+ (save-match-data
+ (if (search-forward cb end 'move)
+ (progn
+ (setq me (match-end 0))
+ (put-text-property
+ (1- me)
+ me
+ 'syntax-table
+ (string-to-syntax syntax)))
+ (setq me end)))
+ (put-text-property
+ (match-beginning 1)
+ me
+ 'syntax-multiline
+ t)))
+
+(defconst cmake--syntax-propertize-function
+ (syntax-propertize-rules
+ ("\\(#\\)\\[\\(=*\\)\\["
+ (1
+ (prog1 "!" (cmake--syntax-propertize-until-bracket-close "!"))))
+ ("\\(\\[\\)\\(=*\\)\\["
+ (1
+ (prog1 "|" (cmake--syntax-propertize-until-bracket-close "|"))))))
+
;; Syntax table for this mode.
(defvar cmake-mode-syntax-table nil
"Syntax table for CMake mode.")
@@ -318,7 +351,10 @@ This puts the mark at the end, and point at the beginning."
; Setup indentation function.
(set (make-local-variable 'indent-line-function) 'cmake-indent)
; Setup comment syntax.
- (set (make-local-variable 'comment-start) "#"))
+ (set (make-local-variable 'comment-start) "#")
+ ;; Setup syntax propertization
+ (set (make-local-variable 'syntax-propertize-function) cmake--syntax-propertize-function)
+ (add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil t))
;; Default cmake-mode key bindings
(define-key cmake-mode-map "\e\C-a" #'cmake-beginning-of-defun)
diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim
index 672bdccc4..0c662faa0 100644
--- a/Auxiliary/vim/indent/cmake.vim
+++ b/Auxiliary/vim/indent/cmake.vim
@@ -59,8 +59,8 @@ fun! CMakeGetIndent(lnum)
let cmake_closing_parens_line = '^\s*\()\+\)\s*$'
- let cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*('
- let cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*('
+ let cmake_indent_begin_regex = '^\s*\(BLOCK\|IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*('
+ let cmake_indent_end_regex = '^\s*\(ENDBLOCK\|ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*('
if this_line =~? cmake_closing_parens_line
if previous_line !~? cmake_indent_open_regex
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index e1a288505..9eb993abf 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -436,6 +436,7 @@ syn keyword cmakeProperty contained
\ XCODE_SCHEME_ENVIRONMENT
\ XCODE_SCHEME_EXECUTABLE
\ XCODE_SCHEME_GUARD_MALLOC
+ \ XCODE_SCHEME_LAUNCH_MODE
\ XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
\ XCODE_SCHEME_MALLOC_GUARD_EDGES
\ XCODE_SCHEME_MALLOC_SCRIBBLE
@@ -444,6 +445,9 @@ syn keyword cmakeProperty contained
\ XCODE_SCHEME_THREAD_SANITIZER_STOP
\ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
\ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ XCODE_SCHEME_LAUNCH_CONFIGURATION
\ XCODE_SCHEME_WORKING_DIRECTORY
\ XCODE_SCHEME_ZOMBIE_OBJECTS
\ XCTEST
@@ -1537,6 +1541,7 @@ syn keyword cmakeVariable contained
\ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
\ CMAKE_XCODE_SCHEME_ENVIRONMENT
\ CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ \ CMAKE_XCODE_SCHEME_LAUNCH_MODE
\ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
\ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
\ CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
@@ -1545,6 +1550,9 @@ syn keyword cmakeVariable contained
\ CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
\ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
\ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION
\ CMAKE_XCODE_SCHEME_WORKING_DIRECTORY
\ CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
\ CPACK_ABSOLUTE_DESTINATION_FILES
@@ -3830,6 +3838,7 @@ syn keyword cmakeCommand
\ add_subdirectory
\ add_test
\ aux_source_directory
+ \ block
\ break
\ build_command
\ cmake_host_system_information
@@ -3857,6 +3866,7 @@ syn keyword cmakeCommand
\ define_property
\ enable_language
\ enable_testing
+ \ endblock
\ endfunction
\ endmacro
\ execute_process
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9de5338c2..2b9eb2d56 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake)
@@ -17,8 +17,8 @@ unset(CMAKE_USER_MAKE_RULES_OVERRIDE_C)
if(MSVC AND NOT CMAKE_VERSION VERSION_LESS 3.15)
# Filter out MSVC runtime library flags that may have come from
# the cache of an existing build tree or from scripts.
- foreach(l C CXX)
- foreach(c DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
+ foreach(l IN ITEMS C CXX)
+ foreach(c IN ITEMS DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
string(REGEX REPLACE "[-/]M[DT]d?( |$)" "" "CMAKE_${l}_FLAGS_${c}" "${CMAKE_${l}_FLAGS_${c}}")
endforeach()
endforeach()
@@ -60,17 +60,6 @@ else()
set(USE_LGPL "")
endif()
-if("${CMake_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
- # Disallow architecture-specific try_run. It may not run on the host.
- macro(TRY_RUN)
- if(CMAKE_TRY_COMPILE_OSX_ARCHITECTURES)
- message(FATAL_ERROR "TRY_RUN not allowed with CMAKE_TRY_COMPILE_OSX_ARCHITECTURES=[${CMAKE_TRY_COMPILE_OSX_ARCHITECTURES}]")
- else()
- _TRY_RUN(${ARGV})
- endif()
- endmacro()
-endif()
-
# Use most-recent available language dialects with GNU and Clang
if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD)
include(${CMake_SOURCE_DIR}/Source/Checks/cm_c11_thread_local.cmake)
@@ -81,7 +70,7 @@ if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD)
endif()
endif()
if(NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMake_NO_CXX_STANDARD)
- if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14)
set(CMAKE_CXX_STANDARD 98)
else()
if(NOT CMAKE_VERSION VERSION_LESS 3.8)
@@ -114,9 +103,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
endif()
# Inform STL library header wrappers whether to use system versions.
-configure_file(${CMake_SOURCE_DIR}/Utilities/std/cmSTL.hxx.in
- ${CMake_BINARY_DIR}/Utilities/cmSTL.hxx
- @ONLY)
+configure_file(Utilities/std/cmSTL.hxx.in Utilities/cmSTL.hxx @ONLY)
# set the internal encoding of CMake to UTF-8
set(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_UTF8)
@@ -143,7 +130,7 @@ option(CMake_BUILD_DEVELOPER_REFERENCE
mark_as_advanced(CMake_BUILD_DEVELOPER_REFERENCE)
# option to build using interprocedural optimizations (IPO/LTO)
-if (NOT CMAKE_VERSION VERSION_LESS 3.12.2)
+if(NOT CMAKE_VERSION VERSION_LESS 3.12.2)
option(CMake_BUILD_LTO "Compile CMake with link-time optimization if supported" OFF)
if(CMake_BUILD_LTO)
include(CheckIPOSupported)
@@ -165,7 +152,7 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES)
# Allow the user to enable/disable all system utility library options by
# defining CMAKE_USE_SYSTEM_LIBRARIES or CMAKE_USE_SYSTEM_LIBRARY_${util}.
set(UTILITIES BZIP2 CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBRHASH LIBUV NGHTTP2 ZLIB ZSTD)
- foreach(util ${UTILITIES})
+ foreach(util IN LISTS UTILITIES)
if(NOT DEFINED CMAKE_USE_SYSTEM_LIBRARY_${util}
AND DEFINED CMAKE_USE_SYSTEM_LIBRARIES)
set(CMAKE_USE_SYSTEM_LIBRARY_${util} "${CMAKE_USE_SYSTEM_LIBRARIES}")
@@ -215,16 +202,14 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES)
mark_as_advanced(CMAKE_USE_SYSTEM_KWIML)
# Mention to the user what system libraries are being used.
- foreach(util ${UTILITIES} KWIML)
+ foreach(util IN LISTS UTILITIES ITEMS KWIML)
if(CMAKE_USE_SYSTEM_${util})
message(STATUS "Using system-installed ${util}")
endif()
endforeach()
# Inform utility library header wrappers whether to use system versions.
- configure_file(${CMake_SOURCE_DIR}/Utilities/cmThirdParty.h.in
- ${CMake_BINARY_DIR}/Utilities/cmThirdParty.h
- @ONLY)
+ configure_file(Utilities/cmThirdParty.h.in Utilities/cmThirdParty.h @ONLY)
endmacro()
@@ -235,7 +220,7 @@ endmacro()
macro(CMAKE_SETUP_TESTING)
if(BUILD_TESTING)
set(CMAKE_TEST_SYSTEM_LIBRARIES 0)
- foreach(util CURL EXPAT ZLIB)
+ foreach(util IN ITEMS CURL EXPAT ZLIB)
if(CMAKE_USE_SYSTEM_${util})
set(CMAKE_TEST_SYSTEM_LIBRARIES 1)
endif()
@@ -250,7 +235,7 @@ macro(CMAKE_SETUP_TESTING)
set(CMAKE_CTEST_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/ctest")
set(CMAKE_CMAKE_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/cmake")
set(CMAKE_CPACK_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/cpack")
- foreach(exe cmake ctest cpack)
+ foreach(exe IN ITEMS cmake ctest cpack)
add_executable(${exe} IMPORTED)
set_property(TARGET ${exe} PROPERTY IMPORTED_LOCATION ${CMake_TEST_EXTERNAL_CMAKE}/${exe})
endforeach()
@@ -262,18 +247,12 @@ macro(CMAKE_SETUP_TESTING)
endif()
# configure some files for testing
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Templates/CTestScript.cmake.in"
- "${CMAKE_CURRENT_BINARY_DIR}/CTestScript.cmake"
- @ONLY)
- configure_file(${CMake_SOURCE_DIR}/Tests/.NoDartCoverage
- ${CMake_BINARY_DIR}/Tests/.NoDartCoverage)
- configure_file(${CMake_SOURCE_DIR}/Tests/.NoDartCoverage
- ${CMake_BINARY_DIR}/Modules/.NoDartCoverage)
- configure_file(${CMake_SOURCE_DIR}/CTestCustom.cmake.in
- ${CMake_BINARY_DIR}/CTestCustom.cmake @ONLY)
+ configure_file(Templates/CTestScript.cmake.in CTestScript.cmake @ONLY)
+ configure_file(Tests/.NoDartCoverage Tests/.NoDartCoverage)
+ configure_file(Tests/.NoDartCoverage Modules/.NoDartCoverage)
+ configure_file(CTestCustom.cmake.in CTestCustom.cmake @ONLY)
if(BUILD_TESTING AND DART_ROOT)
- configure_file(${CMake_SOURCE_DIR}/CMakeLogo.gif
- ${CMake_BINARY_DIR}/Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY)
+ configure_file(CMakeLogo.gif Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY)
endif()
mark_as_advanced(DART_ROOT)
endmacro()
@@ -339,390 +318,6 @@ macro(CMAKE_SET_TARGET_FOLDER tgt folder)
endif()
endmacro()
-
-#-----------------------------------------------------------------------
-# a macro to build the utilities used by CMake
-# Simply to improve readability of the main script.
-#-----------------------------------------------------------------------
-macro (CMAKE_BUILD_UTILITIES)
- find_package(Threads)
-
- # Suppress unnecessary checks in third-party code.
- include(Utilities/cmThirdPartyChecks.cmake)
-
- #---------------------------------------------------------------------
- # Create the kwsys library for CMake.
- set(KWSYS_NAMESPACE cmsys)
- set(KWSYS_USE_SystemTools 1)
- set(KWSYS_USE_Directory 1)
- set(KWSYS_USE_RegularExpression 1)
- set(KWSYS_USE_Base64 1)
- set(KWSYS_USE_MD5 1)
- set(KWSYS_USE_Process 1)
- set(KWSYS_USE_CommandLineArguments 1)
- set(KWSYS_USE_ConsoleBuf 1)
- set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source)
- set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}")
- if(CMake_NO_CXX_STANDARD)
- set(KWSYS_CXX_STANDARD "")
- endif()
- if(CMake_NO_SELF_BACKTRACE)
- set(KWSYS_NO_EXECINFO 1)
- endif()
- if(WIN32)
- # FIXME: Teach KWSys to hard-code these checks on Windows.
- set(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC_COMPILED 0)
- set(KWSYS_C_HAS_PTRDIFF_T_COMPILED 1)
- set(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H_COMPILED 1)
- set(KWSYS_CXX_HAS_RLIMIT64_COMPILED 0)
- set(KWSYS_CXX_HAS_SETENV_COMPILED 0)
- set(KWSYS_CXX_HAS_UNSETENV_COMPILED 0)
- set(KWSYS_CXX_HAS_UTIMENSAT_COMPILED 0)
- set(KWSYS_CXX_HAS_UTIMES_COMPILED 0)
- set(KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED 0)
- set(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED 0)
- set(KWSYS_STL_HAS_WSTRING_COMPILED 1)
- set(KWSYS_SYS_HAS_IFADDRS_H 0)
- endif()
- add_subdirectory(Source/kwsys)
- set(kwsys_folder "Utilities/KWSys")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}")
- if(BUILD_TESTING)
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsC "${kwsys_folder}")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsCxx "${kwsys_folder}")
- CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestSharedForward "${kwsys_folder}")
- endif()
-
- #---------------------------------------------------------------------
- # Setup third-party libraries.
- # Everything in the tree should be able to include files from the
- # Utilities directory.
- if ((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- # using -isystem option generate error "template with C linkage"
- include_directories("${CMake_SOURCE_DIR}/Utilities/std")
- else()
- include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities/std")
- endif()
-
- include_directories("${CMake_BINARY_DIR}/Utilities")
- if ((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- # using -isystem option generate error "template with C linkage"
- include_directories("${CMake_SOURCE_DIR}/Utilities")
- else()
- include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities")
- endif()
-
- #---------------------------------------------------------------------
- # Build CMake std library for CMake and CTest.
- set(CMAKE_STD_LIBRARY cmstd)
- add_subdirectory(Utilities/std)
- CMAKE_SET_TARGET_FOLDER(cmstd "Utilities/std")
-
- # check for the use of system libraries versus builtin ones
- # (a macro defined in this file)
- CMAKE_HANDLE_SYSTEM_LIBRARIES()
-
- if(CMAKE_USE_SYSTEM_KWIML)
- find_package(KWIML 1.0)
- if(NOT KWIML_FOUND)
- message(FATAL_ERROR "CMAKE_USE_SYSTEM_KWIML is ON but KWIML is not found!")
- endif()
- set(CMake_KWIML_LIBRARIES kwiml::kwiml)
- else()
- set(CMake_KWIML_LIBRARIES "")
- if(BUILD_TESTING)
- set(KWIML_TEST_ENABLE 1)
- endif()
- add_subdirectory(Utilities/KWIML)
- endif()
-
- if(CMAKE_USE_SYSTEM_LIBRHASH)
- find_package(LibRHash)
- if(NOT LibRHash_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_LIBRHASH is ON but LibRHash is not found!")
- endif()
- set(CMAKE_LIBRHASH_LIBRARIES LibRHash::LibRHash)
- else()
- set(CMAKE_LIBRHASH_LIBRARIES cmlibrhash)
- add_subdirectory(Utilities/cmlibrhash)
- CMAKE_SET_TARGET_FOLDER(cmlibrhash "Utilities/3rdParty")
- endif()
-
- #---------------------------------------------------------------------
- # Build zlib library for Curl, CMake, and CTest.
- set(CMAKE_ZLIB_HEADER "cm_zlib.h")
- if(CMAKE_USE_SYSTEM_ZLIB)
- find_package(ZLIB)
- if(NOT ZLIB_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_ZLIB is ON but a zlib is not found!")
- endif()
- set(CMAKE_ZLIB_INCLUDES ${ZLIB_INCLUDE_DIR})
- set(CMAKE_ZLIB_LIBRARIES ${ZLIB_LIBRARIES})
- else()
- set(CMAKE_ZLIB_INCLUDES ${CMake_SOURCE_DIR}/Utilities)
- set(CMAKE_ZLIB_LIBRARIES cmzlib)
- set(WITHOUT_ZLIB_DLL "")
- set(WITHOUT_ZLIB_DLL_WITH_LIB cmzlib)
- set(ZLIB_DLL "")
- set(ZLIB_DLL_WITH_LIB cmzlib)
- set(ZLIB_WINAPI "")
- set(ZLIB_WINAPI_COMPILED 0)
- set(ZLIB_WINAPI_WITH_LIB cmzlib)
- add_subdirectory(Utilities/cmzlib)
- CMAKE_SET_TARGET_FOLDER(cmzlib "Utilities/3rdParty")
- endif()
-
- #---------------------------------------------------------------------
- # Build Curl library for CTest.
- if(CMAKE_USE_SYSTEM_CURL)
- find_package(CURL)
- if(NOT CURL_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_CURL is ON but a curl is not found!")
- endif()
- set(CMAKE_CURL_INCLUDES ${CURL_INCLUDE_DIRS})
- set(CMAKE_CURL_LIBRARIES ${CURL_LIBRARIES})
- else()
- set(CURL_SPECIAL_ZLIB_H ${CMAKE_ZLIB_HEADER})
- set(CURL_SPECIAL_LIBZ_INCLUDES ${CMAKE_ZLIB_INCLUDES})
- set(CURL_SPECIAL_LIBZ ${CMAKE_ZLIB_LIBRARIES})
- set(CMAKE_CURL_INCLUDES)
- set(CMAKE_CURL_LIBRARIES cmcurl)
- if(CMAKE_TESTS_CDASH_SERVER)
- set(CMAKE_CURL_TEST_URL "${CMAKE_TESTS_CDASH_SERVER}/user.php")
- endif()
- set(_CMAKE_USE_OPENSSL_DEFAULT OFF)
- if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE
- AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)")
- set(_CMAKE_USE_OPENSSL_DEFAULT ON)
- endif()
- option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT})
- mark_as_advanced(CMAKE_USE_OPENSSL)
- if(CMAKE_USE_OPENSSL)
- set(CURL_CA_BUNDLE "" CACHE FILEPATH "Path to SSL CA Certificate Bundle")
- set(CURL_CA_PATH "" CACHE PATH "Path to SSL CA Certificate Directory")
- mark_as_advanced(CURL_CA_BUNDLE CURL_CA_PATH)
- endif()
- if(NOT CMAKE_USE_SYSTEM_NGHTTP2)
- # Tell curl's FindNGHTTP2 module to use our library.
- set(NGHTTP2_LIBRARY cmnghttp2)
- set(NGHTTP2_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmnghttp2/lib/includes)
- endif()
- add_subdirectory(Utilities/cmcurl)
- CMAKE_SET_TARGET_FOLDER(cmcurl "Utilities/3rdParty")
- CMAKE_SET_TARGET_FOLDER(LIBCURL "Utilities/3rdParty")
- if(NOT CMAKE_USE_SYSTEM_NGHTTP2)
- # Configure after curl to re-use some check results.
- add_subdirectory(Utilities/cmnghttp2)
- CMAKE_SET_TARGET_FOLDER(cmnghttp2 "Utilities/3rdParty")
- endif()
- endif()
-
- #---------------------------------------------------------------------
- # Build expat library for CMake, CTest, and libarchive.
- if(CMAKE_USE_SYSTEM_EXPAT)
- find_package(EXPAT)
- if(NOT EXPAT_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_EXPAT is ON but a expat is not found!")
- endif()
- set(CMAKE_EXPAT_INCLUDES ${EXPAT_INCLUDE_DIRS})
- set(CMAKE_EXPAT_LIBRARIES ${EXPAT_LIBRARIES})
- else()
- set(CMAKE_EXPAT_INCLUDES)
- set(CMAKE_EXPAT_LIBRARIES cmexpat)
- add_subdirectory(Utilities/cmexpat)
- CMAKE_SET_TARGET_FOLDER(cmexpat "Utilities/3rdParty")
- endif()
-
- #---------------------------------------------------------------------
- # Build or use system libbz2 for libarchive.
- if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
- if(CMAKE_USE_SYSTEM_BZIP2)
- find_package(BZip2)
- else()
- set(BZIP2_INCLUDE_DIR
- "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmbzip2")
- set(BZIP2_LIBRARIES cmbzip2)
- set(BZIP2_NEED_PREFIX "")
- set(USE_BZIP2_DLL "")
- set(USE_BZIP2_DLL_WITH_LIB cmbzip2)
- set(USE_BZIP2_STATIC "")
- set(USE_BZIP2_STATIC_WITH_LIB cmbzip2)
- add_subdirectory(Utilities/cmbzip2)
- CMAKE_SET_TARGET_FOLDER(cmbzip2 "Utilities/3rdParty")
- endif()
- endif()
-
- #---------------------------------------------------------------------
- # Build or use system zstd for libarchive.
- if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
- if(NOT CMAKE_USE_SYSTEM_ZSTD)
- set(ZSTD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmzstd")
- set(ZSTD_LIBRARY cmzstd)
- add_subdirectory(Utilities/cmzstd)
- CMAKE_SET_TARGET_FOLDER(cmzstd "Utilities/3rdParty")
- endif()
- endif()
-
- #---------------------------------------------------------------------
- # Build or use system liblzma for libarchive.
- if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
- if(CMAKE_USE_SYSTEM_LIBLZMA)
- find_package(LibLZMA)
- if(NOT LIBLZMA_FOUND)
- message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!")
- endif()
- else()
- add_subdirectory(Utilities/cmliblzma)
- CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty")
- set(LIBLZMA_HAS_AUTO_DECODER 1)
- set(LIBLZMA_HAS_EASY_ENCODER 1)
- set(LIBLZMA_HAS_LZMA_PRESET 1)
- set(LIBLZMA_INCLUDE_DIR
- "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api")
- set(LIBLZMA_LIBRARY cmliblzma)
- set(HAVE_LZMA_STREAM_ENCODER_MT 1)
- endif()
- endif()
-
- #---------------------------------------------------------------------
- # Build or use system libarchive for CMake and CTest.
- if(CMAKE_USE_SYSTEM_LIBARCHIVE)
- find_package(LibArchive 3.3.3)
- if(NOT LibArchive_FOUND)
- message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBARCHIVE is ON but LibArchive is not found!")
- endif()
- set(CMAKE_TAR_INCLUDES ${LibArchive_INCLUDE_DIRS})
- set(CMAKE_TAR_LIBRARIES ${LibArchive_LIBRARIES})
- else()
- set(EXPAT_INCLUDE_DIR ${CMAKE_EXPAT_INCLUDES})
- set(EXPAT_LIBRARY ${CMAKE_EXPAT_LIBRARIES})
- set(ZLIB_INCLUDE_DIR ${CMAKE_ZLIB_INCLUDES})
- set(ZLIB_LIBRARY ${CMAKE_ZLIB_LIBRARIES})
- add_definitions(-DLIBARCHIVE_STATIC)
- set(ENABLE_MBEDTLS OFF)
- set(ENABLE_NETTLE OFF)
- if(DEFINED CMAKE_USE_OPENSSL)
- set(ENABLE_OPENSSL "${CMAKE_USE_OPENSSL}")
- else()
- set(ENABLE_OPENSSL OFF)
- endif()
- set(ENABLE_LIBB2 OFF)
- set(ENABLE_LZ4 OFF)
- set(ENABLE_LZO OFF)
- set(ENABLE_LZMA ON)
- set(ENABLE_ZSTD ON)
- set(ENABLE_ZLIB ON)
- set(ENABLE_BZip2 ON)
- set(ENABLE_LIBXML2 OFF)
- set(ENABLE_EXPAT OFF)
- set(ENABLE_PCREPOSIX OFF)
- set(ENABLE_LibGCC OFF)
- set(ENABLE_CNG OFF)
- set(ENABLE_TAR OFF)
- set(ENABLE_TAR_SHARED OFF)
- set(ENABLE_CPIO OFF)
- set(ENABLE_CPIO_SHARED OFF)
- set(ENABLE_CAT OFF)
- set(ENABLE_CAT_SHARED OFF)
- set(ENABLE_XATTR OFF)
- set(ENABLE_ACL OFF)
- set(ENABLE_ICONV OFF)
- set(ENABLE_TEST OFF)
- set(ENABLE_COVERAGE OFF)
- set(ENABLE_INSTALL OFF)
- set(POSIX_REGEX_LIB "" CACHE INTERNAL "libarchive: No POSIX regular expression support")
- set(ENABLE_SAFESEH "" CACHE INTERNAL "libarchive: No /SAFESEH linker flag")
- set(WINDOWS_VERSION "WIN7" CACHE INTERNAL "libarchive: Set Windows version to use (Windows only)")
- add_subdirectory(Utilities/cmlibarchive)
- CMAKE_SET_TARGET_FOLDER(cmlibarchive "Utilities/3rdParty")
- set(CMAKE_TAR_LIBRARIES cmlibarchive ${BZIP2_LIBRARIES})
- endif()
-
- #---------------------------------------------------------------------
- # Build jsoncpp library.
- if(CMAKE_USE_SYSTEM_JSONCPP)
- find_package(JsonCpp 1.4.1)
- if(NOT JsonCpp_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_JSONCPP is ON but a JsonCpp is not found!")
- endif()
- if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang")
- set_property(TARGET JsonCpp::JsonCpp APPEND PROPERTY
- INTERFACE_COMPILE_OPTIONS -Wno-deprecated-declarations)
- endif()
- set(CMAKE_JSONCPP_LIBRARIES JsonCpp::JsonCpp)
- else()
- set(CMAKE_JSONCPP_LIBRARIES cmjsoncpp)
- add_subdirectory(Utilities/cmjsoncpp)
- CMAKE_SET_TARGET_FOLDER(cmjsoncpp "Utilities/3rdParty")
- endif()
-
- #---------------------------------------------------------------------
- # Build libuv library.
- if(CMAKE_USE_SYSTEM_LIBUV)
- if(WIN32)
- find_package(LibUV 1.38.0)
- else()
- find_package(LibUV 1.28.0)
- endif()
- if(NOT LIBUV_FOUND)
- message(FATAL_ERROR
- "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!")
- endif()
- set(CMAKE_LIBUV_LIBRARIES LibUV::LibUV)
- else()
- set(CMAKE_LIBUV_LIBRARIES cmlibuv)
- add_subdirectory(Utilities/cmlibuv)
- CMAKE_SET_TARGET_FOLDER(cmlibuv "Utilities/3rdParty")
- endif()
-
- #---------------------------------------------------------------------
- # Use curses?
- if(NOT DEFINED BUILD_CursesDialog)
- if (UNIX)
- include(${CMake_SOURCE_DIR}/Source/Checks/Curses.cmake)
- set(BUILD_CursesDialog_DEFAULT "${CMakeCheckCurses_COMPILED}")
- elseif(WIN32)
- set(BUILD_CursesDialog_DEFAULT "OFF")
- endif()
- option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" "${BUILD_CursesDialog_DEFAULT}")
- endif ()
- if(BUILD_CursesDialog)
- if(UNIX)
- set(CURSES_NEED_NCURSES TRUE)
- find_package(Curses)
- if(NOT CURSES_FOUND)
- message(WARNING
- "'ccmake' will not be built because Curses was not found.\n"
- "Turn off BUILD_CursesDialog to suppress this message."
- )
- set(BUILD_CursesDialog 0)
- endif()
- elseif(WIN32)
- # FIXME: Add support for system-provided pdcurses.
- add_subdirectory(Utilities/cmpdcurses)
- set(CURSES_LIBRARY cmpdcurses)
- set(CURSES_INCLUDE_PATH "") # cmpdcurses has usage requirements
- set(CMAKE_USE_SYSTEM_FORM 0)
- set(HAVE_CURSES_USE_DEFAULT_COLORS 1)
- endif()
- endif()
- if(BUILD_CursesDialog)
- if(NOT CMAKE_USE_SYSTEM_FORM)
- add_subdirectory(Source/CursesDialog/form)
- elseif(NOT CURSES_FORM_LIBRARY)
- message( FATAL_ERROR "CMAKE_USE_SYSTEM_FORM in ON but CURSES_FORM_LIBRARY is not set!" )
- endif()
- endif()
-endmacro ()
-
#-----------------------------------------------------------------------
if(NOT CMake_TEST_EXTERNAL_CMAKE)
if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
@@ -749,7 +344,7 @@ include(Source/CMakeVersion.cmake)
# Include the standard Dart testing module
enable_testing()
-include (${CMAKE_ROOT}/Modules/Dart.cmake)
+include(${CMAKE_ROOT}/Modules/Dart.cmake)
# Set up test-time configuration.
set_directory_properties(PROPERTIES
@@ -803,8 +398,9 @@ if(CMake_TEST_EXTERNAL_CMAKE)
endif()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
- # build the utilities (a macro defined in this file)
- CMAKE_BUILD_UTILITIES()
+ find_package(Threads)
+ # build the utilities
+ include(CMakeBuildUtilities)
if(BUILD_QtDialog)
if(APPLE)
@@ -813,10 +409,9 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}")
# make sure CMAKE_INSTALL_PREFIX ends in /
if(NOT CMAKE_INSTALL_PREFIX MATCHES "/$")
- set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/")
+ string(APPEND CMAKE_INSTALL_PREFIX "/")
endif()
- set(CMAKE_INSTALL_PREFIX
- "${CMAKE_INSTALL_PREFIX}CMake.app/Contents")
+ string(APPEND CMAKE_INSTALL_PREFIX "CMake.app/Contents")
endif()
endif()
@@ -829,14 +424,11 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
endif()
# add the uninstall support
- configure_file(
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
- "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
- @ONLY)
+ configure_file(cmake_uninstall.cmake.in cmake_uninstall.cmake @ONLY)
add_custom_target(uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
- include (CMakeCPack.cmake)
+ include(CMakeCPack.cmake)
endif()
@@ -860,10 +452,10 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
-Wshadow -Wpointer-arith -Wformat-security -Wundef
)
- foreach(FLAG_LANG C CXX)
- foreach(FLAG ${${FLAG_LANG}_FLAGS_LIST})
+ foreach(FLAG_LANG IN ITEMS C CXX)
+ foreach(FLAG IN LISTS ${FLAG_LANG}_FLAGS_LIST)
if(NOT " ${CMAKE_${FLAG_LANG}_FLAGS} " MATCHES " ${FLAG} ")
- set(CMAKE_${FLAG_LANG}_FLAGS "${CMAKE_${FLAG_LANG}_FLAGS} ${FLAG}")
+ string(APPEND CMAKE_${FLAG_LANG}_FLAGS " ${FLAG}")
endif()
endforeach()
endforeach()
@@ -883,9 +475,6 @@ add_subdirectory(Tests)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
if(BUILD_TESTING)
CMAKE_SET_TARGET_FOLDER(CMakeLibTests "Tests")
- IF(TARGET CMakeServerLibTests)
- CMAKE_SET_TARGET_FOLDER(CMakeServerLibTests "Tests")
- ENDIF()
endif()
if(TARGET documentation)
CMAKE_SET_TARGET_FOLDER(documentation "Documentation")
@@ -894,7 +483,8 @@ endif()
if(BUILD_TESTING)
add_test(SystemInformationNew "${CMAKE_CMAKE_COMMAND}"
- --system-information -G "${CMAKE_GENERATOR}" )
+ --system-information -G "${CMAKE_GENERATOR}"
+ )
endif()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index 49026a33d..85af8eda8 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -74,6 +74,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
"cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*rand.*may return deterministic values"
"cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*rand.*isn.*t random" # we do not do crypto
"cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*srand.*seed choices are.*poor" # we do not do crypto
+ "cmFindPackageCommand.cxx.*: warning #177-D: parameter .* was declared but never referenced"
"IPA warning: function.*multiply defined in"
"LICENSE WARNING" # PGI license expiry. Not useful in nightly testing.
@@ -83,6 +84,11 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
"compilation completed with warnings" # PGI
"[0-9]+ Warning\\(s\\) detected" # SunPro
+ # Ignore false positive on `cm::optional` usage from GCC
+ "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: warning: '.*cm::optional<CxxModuleMapFormat>::_mem\\)\\)' may be used uninitialized \\[-Wmaybe-uninitialized\\]"
+ "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: note: '.*cm::optional<CxxModuleMapFormat>::_mem\\)\\)' was declared here"
+ "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: warning: '\\*\\(\\(void\\*\\)& modmap_fmt \\+4\\)' may be used uninitialized in this function \\[-Wmaybe-uninitialized\\]"
+
# clang-analyzer exceptions
"cmListFileLexer.c:[0-9]+:[0-9]+: warning: Array subscript is undefined"
"jsoncpp/src/.*:[0-9]+:[0-9]+: warning: Value stored to .* is never read"
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index e6fb20b50..bf8a08218 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -18,12 +18,12 @@ endif()
# not hurt other versions, and this will work into the
# future
if(MSVC OR _INTEL_WINDOWS OR _CLANG_MSVC_WINDOWS)
- add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
+ add_compile_definitions(_CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE)
else()
endif()
if(MSVC)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stack:10000000")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}-stack:10000000")
endif()
# MSVC 14.28 enables C5105, but the Windows SDK 10.0.18362.0 triggers it.
@@ -62,7 +62,7 @@ endif()
# Use 64-bit off_t on 32-bit Linux
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
# ensure 64bit offsets are used for filesystem accesses for 32bit compilation
- add_definitions(-D_FILE_OFFSET_BITS=64)
+ add_compile_definitions(_FILE_OFFSET_BITS=64)
endif()
# Workaround for TOC Overflow on ppc64
@@ -98,7 +98,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND
endif()
endif()
-foreach(lang C CXX)
+foreach(lang IN ITEMS C CXX)
# Suppress warnings from PGI compiler.
if (CMAKE_${lang}_COMPILER_ID STREQUAL "PGI")
set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -w")
@@ -136,3 +136,12 @@ OFF to disable /MP completely." )
endif()
endif()
endif()
+
+# Get rid of excess -Wunused-but-set-variable on release builds with LCC >= 1.26
+foreach(l IN ITEMS C CXX)
+ if(CMAKE_${l}_COMPILER_ID STREQUAL "LCC" AND NOT CMAKE_${l}_COMPILER_VERSION VERSION_LESS 1.26)
+ foreach(c IN ITEMS MINSIZEREL RELEASE RELWITHDEBINFO)
+ string(APPEND "CMAKE_${l}_FLAGS_${c}" " -Wno-unused-but-set-variable")
+ endforeach()
+ endif()
+endforeach()
diff --git a/Copyright.txt b/Copyright.txt
index 2cf176910..bd45dd1f3 100644
--- a/Copyright.txt
+++ b/Copyright.txt
@@ -53,6 +53,7 @@ The following individuals and institutions are among the Contributors:
* Clement Creusot <creusot@cs.york.ac.uk>
* Daniel Blezek <blezek@gmail.com>
* Daniel Pfeifer <daniel@pfeifer-mail.de>
+* Dawid Wróbel <me@dawidwrobel.com>
* Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
* Eran Ifrah <eran.ifrah@gmail.com>
* Esben Mose Hansen, Ange Optimization ApS
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index cd3c78baf..bd55e24c7 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -15,6 +15,7 @@ The general signature is:
[PATHS [path | ENV var]... ]
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
+ [VALIDATOR function]
[DOC "cache documentation string"]
[NO_CACHE]
[REQUIRED]
@@ -66,6 +67,31 @@ Options include:
Specify additional subdirectories to check below each directory
location otherwise considered.
+``VALIDATOR``
+ .. versionadded:: 3.25
+
+ Specify a :command:`function` to be called for each candidate item found
+ (a :command:`macro` cannot be provided, that will result in an error).
+ Two arguments will be passed to the validator function: the name of a
+ result variable, and the absolute path to the candidate item. The item
+ will be accepted and the search will end unless the function sets the
+ value in the result variable to false in the calling scope. The result
+ variable will hold a true value when the validator function is entered.
+
+ .. parsed-literal::
+
+ function(my_check validator_result_var item)
+ if(NOT item MATCHES ...)
+ set(${validator_result_var} FALSE PARENT_SCOPE)
+ endif()
+ endfunction()
+
+ |FIND_XXX| (result NAMES ... VALIDATOR my_check)
+
+ Note that if a cached result is used, the search is skipped and any
+ ``VALIDATOR`` is ignored. The cached result is not required to pass the
+ validation function.
+
``DOC``
Specify the documentation string for the ``<VAR>`` cache entry.
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 9e60d2d68..99adc85c1 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -67,6 +67,8 @@ The options are:
Each byproduct file will be marked with the :prop_sf:`GENERATED`
source file property automatically.
+ *See policy* :policy:`CMP0058` *for the motivation behind this feature.*
+
Explicit specification of byproducts is supported by the
:generator:`Ninja` generator to tell the ``ninja`` build tool
how to regenerate byproducts when they are missing. It is
@@ -434,7 +436,7 @@ one of the keywords to make clear the behavior they expect.
Because generator expressions can be used in custom commands,
it is possible to define ``COMMAND`` lines or whole custom commands
which evaluate to empty strings for certain configurations.
- For **Visual Studio 2010 (and newer)** generators these command
+ For **Visual Studio 11 2012 (and newer)** generators these command
lines or custom commands will be omitted for the specific
configuration and no "empty-string-command" will be added.
diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst
index def23fafd..d8882ca99 100644
--- a/Help/command/add_custom_target.rst
+++ b/Help/command/add_custom_target.rst
@@ -42,6 +42,8 @@ The options are:
Each byproduct file will be marked with the :prop_sf:`GENERATED`
source file property automatically.
+ *See policy* :policy:`CMP0058` *for the motivation behind this feature.*
+
Explicit specification of byproducts is supported by the
:generator:`Ninja` generator to tell the ``ninja`` build tool
how to regenerate byproducts when they are missing. It is
diff --git a/Help/command/add_subdirectory.rst b/Help/command/add_subdirectory.rst
index 8dba986ba..13cae1000 100644
--- a/Help/command/add_subdirectory.rst
+++ b/Help/command/add_subdirectory.rst
@@ -5,7 +5,7 @@ Add a subdirectory to the build.
.. code-block:: cmake
- add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
+ add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])
Adds a subdirectory to the build. The source_dir specifies the
directory in which the source CMakeLists.txt and code files are
@@ -33,3 +33,10 @@ dependencies supersede this exclusion. If a target built by the
parent project depends on a target in the subdirectory, the dependee
target will be included in the parent project build system to satisfy
the dependency.
+
+If the ``SYSTEM`` argument is provided, the :prop_dir:`SYSTEM` directory
+property of the subdirectory will be set to true. This property is
+used to initialize the :prop_tgt:`SYSTEM` property of each target
+created in that subdirectory. The include directories of targets with
+:prop_tgt:`SYSTEM` set to true will be treated as ``SYSTEM`` when
+compiling consumers.
diff --git a/Help/command/block.rst b/Help/command/block.rst
new file mode 100644
index 000000000..dfd60d446
--- /dev/null
+++ b/Help/command/block.rst
@@ -0,0 +1,76 @@
+block
+-----
+
+.. versionadded:: 3.25
+
+Evaluate a group of commands with a dedicated variable and/or policy scope.
+
+.. code-block:: cmake
+
+ block([SCOPE_FOR [POLICIES] [VARIABLES] ] [PROPAGATE <var-name>...])
+ <commands>
+ endblock()
+
+All commands between ``block()`` and the matching :command:`endblock` are
+recorded without being invoked. Once the :command:`endblock` is evaluated, the
+recorded list of commands is invoked inside the requested scopes, then the
+scopes created by the ``block()`` command are removed.
+
+``SCOPE_FOR``
+ Specify which scopes must be created.
+
+ ``POLICIES``
+ Create a new policy scope. This is equivalent to
+ :command:`cmake_policy(PUSH)`.
+
+ ``VARIABLES``
+ Create a new variable scope.
+
+ If ``SCOPE_FOR`` is not specified, this is equivalent to:
+
+ .. code-block:: cmake
+
+ block(SCOPE_FOR VARIABLES POLICIES)
+
+``PROPAGATE``
+ When a variable scope is created by the :command:`block` command, this
+ option sets or unsets the specified variables in the parent scope. This is
+ equivalent to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)`
+ commands.
+
+ .. code-block:: cmake
+
+ set(var1 "INIT1")
+ set(var2 "INIT2")
+
+ block(PROPAGATE var1 var2)
+ set(var1 "VALUE1")
+ unset(var2)
+ endblock()
+
+ # Now var1 holds VALUE1, and var2 is unset
+
+ This option is only allowed when a variable scope is created. An error will
+ be raised in the other cases.
+
+When the ``block()`` is inside a :command:`foreach` or :command:`while`
+command, the :command:`break` and :command:`continue` commands can be used
+inside the block.
+
+.. code-block:: cmake
+
+ while(TRUE)
+ block()
+ ...
+ # the break() command will terminate the while() command
+ break()
+ endblock()
+ endwhile()
+
+
+See Also
+^^^^^^^^
+
+ * :command:`endblock`
+ * :command:`return`
+ * :command:`cmake_policy`
diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst
index a03979d10..3d86a2e03 100644
--- a/Help/command/build_command.rst
+++ b/Help/command/build_command.rst
@@ -24,12 +24,12 @@ options, if any. The trailing ``-- -i`` option is added for
:ref:`Makefile Generators` if policy :policy:`CMP0061` is not set to
``NEW``.
-When invoked, this ``cmake --build`` command line will launch the
+When invoked, this :option:`cmake --build` command line will launch the
underlying build system tool.
.. versionadded:: 3.21
- The ``PARALLEL_LEVEL`` argument can be used to set the ``--parallel``
- flag.
+ The ``PARALLEL_LEVEL`` argument can be used to set the
+ :option:`--parallel <cmake--build --parallel>` flag.
.. code-block:: cmake
@@ -39,7 +39,7 @@ This second signature is deprecated, but still available for backwards
compatibility. Use the first signature instead.
It sets the given ``<cachevariable>`` to a command-line string as
-above but without the ``--target`` option.
+above but without the :option:`--target <cmake--build --target>` option.
The ``<makecommand>`` is ignored but should be the full path to
devenv, nmake, make or one of the end user build tools
for legacy invocations.
diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst
index cb8d60b73..8801a9fdf 100644
--- a/Help/command/cmake_language.rst
+++ b/Help/command/cmake_language.rst
@@ -14,6 +14,7 @@ Synopsis
cmake_language(`EVAL`_ CODE <code>...)
cmake_language(`DEFER`_ <options>... CALL <command> [<arg>...])
cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...)
+ cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>)
Introduction
^^^^^^^^^^^^
@@ -50,6 +51,7 @@ is equivalent to
To ensure consistency of the code, the following commands are not allowed:
* ``if`` / ``elseif`` / ``else`` / ``endif``
+ * ``block`` / ``endblock``
* ``while`` / ``endwhile``
* ``foreach`` / ``endforeach``
* ``function`` / ``endfunction``
@@ -491,3 +493,29 @@ calling the provider command recursively for the same dependency.
SET_DEPENDENCY_PROVIDER mycomp_provide_dependency
SUPPORTED_METHODS FIND_PACKAGE
)
+
+Getting current message log level
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.25
+
+.. _GET_MESSAGE_LOG_LEVEL:
+.. _query_message_log_level:
+
+.. code-block:: cmake
+
+ cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>)
+
+Writes the current :command:`message` logging level
+into the given ``<output_variable>``.
+
+See :command:`message` for the possible logging levels.
+
+The current message logging level can be set either using the
+:option:`--log-level <cmake --log-level>`
+command line option of the :manual:`cmake(1)` program or using
+the :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable.
+
+If both the command line option and the variable are set, the command line
+option takes precedence. If neither are set, the default logging level
+is returned.
diff --git a/Help/command/cmake_policy.rst b/Help/command/cmake_policy.rst
index 94060d9b8..54fc54815 100644
--- a/Help/command/cmake_policy.rst
+++ b/Help/command/cmake_policy.rst
@@ -103,6 +103,47 @@ Calls to the :command:`cmake_minimum_required(VERSION)`,
``cmake_policy(VERSION)``, or ``cmake_policy(SET)`` commands
influence only the current top of the policy stack.
+.. versionadded:: 3.25
+ The :command:`block` and :command:`endblock` commands offer a more flexible
+ and more secure way to manage the policy stack. The pop action is done
+ automatically when the :command:`endblock` command is executed, so it avoid
+ to call the :command:`cmake_policy(POP)` command before each
+ :command:`return` command.
+
+ .. code-block:: cmake
+
+ # stack management with cmake_policy()
+ function(my_func)
+ cmake_policy(PUSH)
+ cmake_policy(SET ...)
+ if (<cond1>)
+ ...
+ cmake_policy(POP)
+ return()
+ elseif(<cond2>)
+ ...
+ cmake_policy(POP)
+ return()
+ endif()
+ ...
+ cmake_policy(POP)
+ endfunction()
+
+ # stack management with block()/endblock()
+ function(my_func)
+ block(SCOPE_FOR POLICIES)
+ cmake_policy(SET ...)
+ if (<cond1>)
+ ...
+ return()
+ elseif(<cond2>)
+ ...
+ return()
+ endif()
+ ...
+ endblock()
+ endfunction()
+
Commands created by the :command:`function` and :command:`macro`
commands record policy settings when they are created and
use the pre-record policies when they are invoked. If the function or
diff --git a/Help/command/continue.rst b/Help/command/continue.rst
index f62802e2d..e8012ee30 100644
--- a/Help/command/continue.rst
+++ b/Help/command/continue.rst
@@ -9,8 +9,8 @@ Continue to the top of enclosing foreach or while loop.
continue()
-The ``continue`` command allows a cmake script to abort the rest of a block
-in a :command:`foreach` or :command:`while` loop, and start at the top of
-the next iteration.
+The ``continue()`` command allows a cmake script to abort the rest of the
+current iteration of a :command:`foreach` or :command:`while` loop, and start
+at the top of the next iteration.
See also the :command:`break` command.
diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst
index e05df1afc..8c81f2d52 100644
--- a/Help/command/ctest_build.rst
+++ b/Help/command/ctest_build.rst
@@ -40,8 +40,8 @@ The options are:
``CONFIGURATION <config>``
Specify the build configuration (e.g. ``Debug``). If not
specified the ``CTEST_BUILD_CONFIGURATION`` variable will be checked.
- Otherwise the ``-C <cfg>`` option given to the :manual:`ctest(1)`
- command will be used, if any.
+ Otherwise the :option:`-C \<cfg\> <ctest -C>` option given to the
+ :manual:`ctest(1)` command will be used, if any.
``PARALLEL_LEVEL <parallel>``
.. versionadded:: 3.21
@@ -54,7 +54,7 @@ The options are:
Pass additional arguments to the underlying build command.
If not specified the ``CTEST_BUILD_FLAGS`` variable will be checked.
This can, e.g., be used to trigger a parallel build using the
- ``-j`` option of make. See the :module:`ProcessorCount` module
+ ``-j`` option of ``make``. See the :module:`ProcessorCount` module
for an example.
``PROJECT_NAME <project-name>``
diff --git a/Help/command/ctest_run_script.rst b/Help/command/ctest_run_script.rst
index 5ec543ed1..a2b348f4c 100644
--- a/Help/command/ctest_run_script.rst
+++ b/Help/command/ctest_run_script.rst
@@ -1,15 +1,15 @@
ctest_run_script
----------------
-runs a ctest -S script
+runs a :option:`ctest -S` script
::
ctest_run_script([NEW_PROCESS] script_file_name script_file_name1
script_file_name2 ... [RETURN_VALUE var])
-Runs a script or scripts much like if it was run from ctest -S. If no
-argument is provided then the current script is run using the current
+Runs a script or scripts much like if it was run from :option:`ctest -S`.
+If no argument is provided then the current script is run using the current
settings of the variables. If ``NEW_PROCESS`` is specified then each
script will be run in a separate process.If ``RETURN_VALUE`` is specified
the return value of the last script run will be put into ``var``.
diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst
index c0f3c6d3c..921279a43 100644
--- a/Help/command/ctest_start.rst
+++ b/Help/command/ctest_start.rst
@@ -45,7 +45,7 @@ The parameters are as follows:
ctest_start(Experimental GROUP GroupExperimental)
- Later, in another ``ctest -S`` script:
+ Later, in another :option:`ctest -S` script:
.. code-block:: cmake
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index 65f82d703..4f9f89198 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -109,8 +109,9 @@ The options are:
While running tests in parallel, try not to start tests when they
may cause the CPU load to pass above a given threshold. If not
specified the :variable:`CTEST_TEST_LOAD` variable will be checked,
- and then the ``--test-load`` command-line argument to :manual:`ctest(1)`.
- See also the ``TestLoad`` setting in the :ref:`CTest Test Step`.
+ and then the :option:`--test-load <ctest --test-load>` command-line
+ argument to :manual:`ctest(1)`. See also the ``TestLoad`` setting
+ in the :ref:`CTest Test Step`.
``REPEAT <mode>:<n>``
.. versionadded:: 3.17
@@ -176,8 +177,9 @@ See also the :variable:`CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE`,
:variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE` and
:variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variables, along with their
corresponding :manual:`ctest(1)` command line options
-``--test-output-size-passed``, ``--test-output-size-failed``, and
-``--test-output-truncation``.
+:option:`--test-output-size-passed <ctest --test-output-size-passed>`,
+:option:`--test-output-size-failed <ctest --test-output-size-failed>`, and
+:option:`--test-output-truncation <ctest --test-output-truncation>`.
.. _`Additional Test Measurements`:
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index d2acbc85c..d9103b890 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -1,13 +1,14 @@
enable_language
---------------
-Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc)
+
+Enable languages (CXX/C/OBJC/OBJCXX/Fortran/etc)
.. code-block:: cmake
- enable_language(<lang> [OPTIONAL] )
+ enable_language(<lang>... [OPTIONAL])
-Enables support for the named language in CMake. This is
-the same as the :command:`project` command but does not create any of the extra
+Enables support for the named languages in CMake. This is the same as
+the :command:`project` command but does not create any of the extra
variables that are created by the project command. Example languages
are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``,
``HIP``, ``ISPC``, and ``ASM``.
diff --git a/Help/command/endblock.rst b/Help/command/endblock.rst
new file mode 100644
index 000000000..3b21c1205
--- /dev/null
+++ b/Help/command/endblock.rst
@@ -0,0 +1,11 @@
+endblock
+--------
+
+.. versionadded:: 3.25
+
+Ends a list of commands in a :command:`block` and removes the scopes
+created by the :command:`block` command.
+
+.. code-block:: cmake
+
+ endblock()
diff --git a/Help/command/export.rst b/Help/command/export.rst
index dc6964524..0f79f6337 100644
--- a/Help/command/export.rst
+++ b/Help/command/export.rst
@@ -25,7 +25,8 @@ Exporting Targets
.. code-block:: cmake
export(TARGETS <target>... [NAMESPACE <namespace>]
- [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])
+ [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES]
+ [CXX_MODULES_DIRECTORY <directory>])
Creates a file ``<filename>`` that may be included by outside projects to
import targets named by ``<target>...`` from the current project's build tree.
@@ -52,6 +53,16 @@ The options are:
in the export, even when policy :policy:`CMP0022` is NEW. This is useful
to support consumers using CMake versions older than 2.8.12.
+``CXX_MODULES_DIRECTORY <directory>``
+
+ .. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Export C++ module properties to files under the given directory. Each file
+ will be named according to the target's export name (without any namespace).
+ These files will automatically be included from the export file.
+
This signature requires all targets to be listed explicitly. If a library
target is included in the export, but a target to which it links is not
included, the behavior is unspecified. See the `export(EXPORT)`_ signature
@@ -95,7 +106,8 @@ Exporting Targets matching install(EXPORT)
.. code-block:: cmake
- export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>])
+ export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>]
+ [CXX_MODULES_DIRECTORY <directory>])
Creates a file ``<filename>`` that may be included by outside projects to
import targets from the current project's build tree. This is the same
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 3374d2d1c..fbe2a8154 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -1121,8 +1121,11 @@ Additional options to ``DOWNLOAD`` are:
Verify that the downloaded content hash matches the expected value, where
``ALGO`` is one of the algorithms supported by ``file(<HASH>)``.
- If it does not match, the operation fails with an error. It is an error to
- specify this if ``DOWNLOAD`` is not given a ``<file>``.
+ If the file already exists and matches the hash, the download is skipped.
+ If the file already exists and does not match the hash, the file is
+ downloaded again. If after download the file does not match the hash, the
+ operation fails with an error. It is an error to specify this option if
+ ``DOWNLOAD`` is not given a ``<file>``.
``EXPECTED_MD5 <value>``
Historical short-hand for ``EXPECTED_HASH MD5=<value>``. It is an error to
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index c96d84e18..c99c73dd3 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -285,29 +285,40 @@ CMake constructs a set of possible installation prefixes for the
package. Under each prefix several directories are searched for a
configuration file. The tables below show the directories searched.
Each entry is meant for installation trees following Windows (``W``), UNIX
-(``U``), or Apple (``A``) conventions::
-
- <prefix>/ (W)
- <prefix>/(cmake|CMake)/ (W)
- <prefix>/<name>*/ (W)
- <prefix>/<name>*/(cmake|CMake)/ (W)
- <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ (U)
- <prefix>/(lib/<arch>|lib*|share)/<name>*/ (U)
- <prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (U)
- <prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/ (W/U)
- <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/ (W/U)
- <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
+(``U``), or Apple (``A``) conventions:
+
+==================================================================== ==========
+ Entry Convention
+==================================================================== ==========
+ ``<prefix>/`` W
+ ``<prefix>/(cmake|CMake)/`` W
+ ``<prefix>/<name>*/`` W
+ ``<prefix>/<name>*/(cmake|CMake)/`` W
+ ``<prefix>/<name>*/(cmake|CMake)/<name>*/`` [#]_ W
+ ``<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/`` U
+ ``<prefix>/(lib/<arch>|lib*|share)/<name>*/`` U
+ ``<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/`` U
+ ``<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/`` W/U
+ ``<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/`` W/U
+ ``<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/`` W/U
+==================================================================== ==========
+
+.. [#] .. versionadded:: 3.25
On systems supporting macOS :prop_tgt:`FRAMEWORK` and :prop_tgt:`BUNDLE`, the
following directories are searched for Frameworks or Application Bundles
-containing a configuration file::
-
- <prefix>/<name>.framework/Resources/ (A)
- <prefix>/<name>.framework/Resources/CMake/ (A)
- <prefix>/<name>.framework/Versions/*/Resources/ (A)
- <prefix>/<name>.framework/Versions/*/Resources/CMake/ (A)
- <prefix>/<name>.app/Contents/Resources/ (A)
- <prefix>/<name>.app/Contents/Resources/CMake/ (A)
+containing a configuration file:
+
+=========================================================== ==========
+ Entry Convention
+=========================================================== ==========
+ ``<prefix>/<name>.framework/Resources/`` A
+ ``<prefix>/<name>.framework/Resources/CMake/`` A
+ ``<prefix>/<name>.framework/Versions/*/Resources/`` A
+ ``<prefix>/<name>.framework/Versions/*/Resources/CMake/`` A
+ ``<prefix>/<name>.app/Contents/Resources/`` A
+ ``<prefix>/<name>.app/Contents/Resources/CMake/`` A
+=========================================================== ==========
In all cases the ``<name>`` is treated as case-insensitive and corresponds
to any of the names specified (``<PackageName>`` or names given by ``NAMES``).
@@ -368,7 +379,7 @@ enabled.
See policy :policy:`CMP0074`.
2. Search paths specified in cmake-specific cache variables. These
- are intended to be used on the command line with a ``-DVAR=value``.
+ are intended to be used on the command line with a :option:`-DVAR=VALUE <cmake -D>`.
The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`.
This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the
:variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``:
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index d9f54ca75..ddf8dfa84 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -130,3 +130,11 @@ yields
-- en=two, ba=dua
-- en=three, ba=tiga
-- en=four, ba=
+
+See Also
+^^^^^^^^
+
+* :command:`break`
+* :command:`continue`
+* :command:`endforeach`
+* :command:`while`
diff --git a/Help/command/function.rst b/Help/command/function.rst
index 3d25aa45f..fc55c034f 100644
--- a/Help/command/function.rst
+++ b/Help/command/function.rst
@@ -73,3 +73,9 @@ argument. Referencing to ``ARGV#`` arguments beyond ``ARGC`` have
undefined behavior. Checking that ``ARGC`` is greater than ``#`` is
the only way to ensure that ``ARGV#`` was passed to the function as an
extra argument.
+
+See Also
+^^^^^^^^
+
+* :command:`endfunction`
+* :command:`return`
diff --git a/Help/command/get_test_property.rst b/Help/command/get_test_property.rst
index e02b9bc77..6bcc1ef2a 100644
--- a/Help/command/get_test_property.rst
+++ b/Help/command/get_test_property.rst
@@ -16,6 +16,7 @@ relevant parent scope as described for the :command:`define_property`
command and if still unable to find the property, ``VAR`` will be set to
an empty string.
-For a list of standard properties you can type ``cmake --help-property-list``.
+For a list of standard properties you can type
+:option:`cmake --help-property-list`.
See also the more general :command:`get_property` command.
diff --git a/Help/command/if.rst b/Help/command/if.rst
index 301cdce03..b72769f6d 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -424,3 +424,10 @@ There is no automatic evaluation for environment or cache
:ref:`Variable References`. Their values must be referenced as
``$ENV{<name>}`` or ``$CACHE{<name>}`` wherever the above-documented
condition syntax accepts ``<variable|string>``.
+
+See also
+^^^^^^^^
+
+ * :command:`else`
+ * :command:`elseif`
+ * :command:`endif`
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 973aa31d8..feff4360c 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -132,7 +132,7 @@ Installing Targets
install(TARGETS targets... [EXPORT <export-name>]
[RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
- PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>]
+ PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
@@ -215,11 +215,21 @@ that may be installed:
``/blah/include/myproj/here.h`` with a base directory ``/blah/include``
would be installed to ``myproj/here.h`` below the destination.
+``CXX_MODULES_BMI``
+
+ .. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Any module files from C++ modules from ``PUBLIC`` sources in a file set of
+ type ``CXX_MODULES`` will be installed to the given ``DESTINATION``. All
+ modules are placed directly in the destination as no directory structure is
+ derived from the names of the modules. An empty ``DESTINATION`` may be used
+ to suppress installing these files (for use in generic code).
+
For each of these arguments given, the arguments following them only apply
to the target or file type specified in the argument. If none is given, the
-installation properties apply to all target types. If only one is given then
-only targets of that type will be installed (which can be used to install
-just a DLL or just an import library.)
+installation properties apply to all target types.
For regular executables, static libraries and shared libraries, the
``DESTINATION`` argument is not required. For these target types, when
@@ -233,6 +243,14 @@ Apple bundles and frameworks. A destination can be omitted for interface and
object libraries, but they are handled differently (see the discussion of this
topic toward the end of this section).
+For shared libraries on DLL platforms, if neither ``RUNTIME`` nor ``ARCHIVE``
+destinations are specified, both the ``RUNTIME`` and ``ARCHIVE`` components are
+installed to their default destinations. If either a ``RUNTIME`` or ``ARCHIVE``
+destination is specified, the component is installed to that destination, and
+the other component is not installed. If both ``RUNTIME`` and ``ARCHIVE``
+destinations are specified, then both components are installed to their
+respective destinations.
+
The following table shows the target types with their associated variables and
built-in defaults that apply when no destination is given:
@@ -778,9 +796,10 @@ Installing Exports
.. code-block:: cmake
install(EXPORT <export-name> DESTINATION <dir>
- [NAMESPACE <namespace>] [[FILE <name>.cmake]|
+ [NAMESPACE <namespace>] [FILE <name>.cmake]
[PERMISSIONS permissions...]
- [CONFIGURATIONS [Debug|Release|...]]
+ [CONFIGURATIONS [Debug|Release|...]
+ [CXX_MODULES_DIRECTORY <directory>]
[EXPORT_LINK_INTERFACE_LIBRARIES]
[COMPONENT <component>]
[EXCLUDE_FROM_ALL])
@@ -836,6 +855,18 @@ library is always installed if the headers and CMake export file are present.
to an ndk build system complete with transitive dependencies, include flags
and defines required to use the libraries.
+``CXX_MODULES_DIRECTORY``
+
+ .. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Specify a subdirectory to store C++ module information for targets in the
+ export set. This directory will be populated with files which add the
+ necessary target property information to the relevant targets. Note that
+ without this information, none of the C++ modules which are part of the
+ targets in the export set will support being imported in consuming targets.
+
The ``EXPORT`` form is useful to help outside projects use targets built
and installed by the current project. For example, the code
@@ -932,12 +963,12 @@ Generated Installation Script
.. note::
Use of this feature is not recommended. Please consider using the
- ``--install`` argument of :manual:`cmake(1)` instead.
+ :option:`cmake --install` instead.
The ``install()`` command generates a file, ``cmake_install.cmake``, inside
the build directory, which is used internally by the generated install target
-and by CPack. You can also invoke this script manually with ``cmake -P``. This
-script accepts several variables:
+and by CPack. You can also invoke this script manually with
+:option:`cmake -P`. This script accepts several variables:
``COMPONENT``
Set this variable to install only a single CPack component as opposed to all
diff --git a/Help/command/message.rst b/Help/command/message.rst
index ca4f5c1fa..77d21c83c 100644
--- a/Help/command/message.rst
+++ b/Help/command/message.rst
@@ -83,8 +83,9 @@ are sent to stderr and are not prefixed with hyphens. The
:manual:`CMake GUI <cmake-gui(1)>` displays all messages in its log area.
The :manual:`curses interface <ccmake(1)>` shows ``STATUS`` to ``TRACE``
messages one at a time on a status line and other messages in an
-interactive pop-up box. The ``--log-level`` command-line option to each of
-these tools can be used to control which messages will be shown.
+interactive pop-up box. The :option:`--log-level <cmake --log-level>`
+command-line option to each of these tools can be used to control which
+messages will be shown.
.. versionadded:: 3.17
To make a log level persist between CMake runs, the
@@ -104,7 +105,7 @@ these tools can be used to control which messages will be shown.
list variable to a dot-separated string. The message context will always
appear before any indenting content but after any automatically added leading
hyphens. By default, message context is not shown, it has to be explicitly
- enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context``
+ enabled by giving the :option:`cmake --log-context`
command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for
usage examples.
diff --git a/Help/command/return.rst b/Help/command/return.rst
index ec009d8c8..3013b5285 100644
--- a/Help/command/return.rst
+++ b/Help/command/return.rst
@@ -5,16 +5,87 @@ Return from a file, directory or function.
.. code-block:: cmake
- return()
+ return([PROPAGATE <var-name>...])
-Returns from a file, directory or function. When this command is
-encountered in an included file (via :command:`include` or
+When this command is encountered in an included file (via :command:`include` or
:command:`find_package`), it causes processing of the current file to stop
and control is returned to the including file. If it is encountered in a
-file which is not included by another file, e.g. a ``CMakeLists.txt``,
+file which is not included by another file, e.g. a ``CMakeLists.txt``,
deferred calls scheduled by :command:`cmake_language(DEFER)` are invoked and
-control is returned to the parent directory if there is one. If return is
-called in a function, control is returned to the caller of the function.
+control is returned to the parent directory if there is one.
-Note that a :command:`macro <macro>`, unlike a :command:`function <function>`,
+If ``return()`` is called in a function, control is returned to the caller
+of that function. Note that a :command:`macro`, unlike a :command:`function`,
is expanded in place and therefore cannot handle ``return()``.
+
+Policy :policy:`CMP0140` controls the behavior regarding the arguments of the
+command. All arguments are ignored unless that policy is set to ``NEW``.
+
+``PROPAGATE``
+ .. versionadded:: 3.25
+
+ This option sets or unsets the specified variables in the parent directory or
+ function caller scope. This is equivalent to :command:`set(PARENT_SCOPE)` or
+ :command:`unset(PARENT_SCOPE)` commands, except for the way it interacts
+ with the :command:`block` command, as described below.
+
+ The ``PROPAGATE`` option can be very useful in conjunction with the
+ :command:`block` command. A :command:`return` will propagate the
+ specified variables through any enclosing block scopes created by the
+ :command:`block` commands. Inside a function, this ensures the variables
+ are propagated to the function's caller, regardless of any blocks within
+ the function. If not inside a function, it ensures the variables are
+ propagated to the parent file or directory scope. For example:
+
+ .. code-block:: cmake
+ :caption: CMakeLists.txt
+
+ cmake_version_required(VERSION 3.25)
+ project(example)
+
+ set(var1 "top-value")
+
+ block(SCOPE_FOR VARIABLES)
+ add_subdirectory(subDir)
+ # var1 has the value "block-nested"
+ endblock()
+
+ # var1 has the value "top-value"
+
+ .. code-block:: cmake
+ :caption: subDir/CMakeLists.txt
+
+ function(multi_scopes result_var1 result_var2)
+ block(SCOPE_FOR VARIABLES)
+ # This would only propagate out of the immediate block, not to
+ # the caller of the function.
+ #set(${result_var1} "new-value" PARENT_SCOPE)
+ #unset(${result_var2} PARENT_SCOPE)
+
+ # This propagates the variables through the enclosing block and
+ # out to the caller of the function.
+ set(${result_var1} "new-value")
+ unset(${result_var2})
+ return(PROPAGATE ${result_var1} ${result_var2})
+ endblock()
+ endfunction()
+
+ set(var1 "some-value")
+ set(var2 "another-value")
+
+ multi_scopes(var1 var2)
+ # Now var1 will hold "new-value" and var2 will be unset
+
+ block(SCOPE_FOR VARIABLES)
+ # This return() will set var1 in the directory scope that included us
+ # via add_subdirectory(). The surrounding block() here does not limit
+ # propagation to the current file, but the block() in the parent
+ # directory scope does prevent propagation going any further.
+ set(var1 "block-nested")
+ return(PROPAGATE var1)
+ endblock()
+
+See Also
+^^^^^^^^
+
+ * :command:`block`
diff --git a/Help/command/set.rst b/Help/command/set.rst
index af862e4da..90b57d23f 100644
--- a/Help/command/set.rst
+++ b/Help/command/set.rst
@@ -22,12 +22,17 @@ Set Normal Variable
Sets the given ``<variable>`` in the current function or directory scope.
If the ``PARENT_SCOPE`` option is given the variable will be set in
-the scope above the current scope. Each new directory or function
-creates a new scope. This command will set the value of a variable
-into the parent directory or calling function (whichever is applicable
-to the case at hand). The previous state of the variable's value stays the
-same in the current scope (e.g., if it was undefined before, it is still
-undefined and if it had a value, it is still that value).
+the scope above the current scope. Each new directory or :command:`function`
+command creates a new scope. A scope can also be created with the
+:command:`block` command. This command will set the value of a variable into
+the parent directory, calling function or encompassing scope (whichever is
+applicable to the case at hand). The previous state of the variable's value
+stays the same in the current scope (e.g., if it was undefined before, it is
+still undefined and if it had a value, it is still that value).
+
+The :command:`block(PROPAGATE)` and :command:`return(PROPAGATE)` commands can
+be used as an alternate method to the :command:`set(PARENT_SCOPE)` and
+:command:`unset(PARENT_SCOPE)` commands to update the parent scope.
Set Cache Entry
^^^^^^^^^^^^^^^
@@ -78,7 +83,7 @@ option is given then the cache entry will be set to the given value.
It is possible for the cache entry to exist prior to the call but
have no type set if it was created on the :manual:`cmake(1)` command
-line by a user through the ``-D<var>=<value>`` option without
+line by a user through the :option:`-D\<var\>=\<value\> <cmake -D>` option without
specifying a type. In this case the ``set`` command will add the
type. Furthermore, if the ``<type>`` is ``PATH`` or ``FILEPATH``
and the ``<value>`` provided on the command line is a relative path,
diff --git a/Help/command/target_compile_definitions.rst b/Help/command/target_compile_definitions.rst
index 3fb113a92..2d292afdd 100644
--- a/Help/command/target_compile_definitions.rst
+++ b/Help/command/target_compile_definitions.rst
@@ -15,9 +15,9 @@ named ``<target>`` must have been created by a command such as
:ref:`ALIAS target <Alias Targets>`.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
-items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of
-``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+specify the :ref:`scope <Target Usage Requirements>` of the following arguments.
+``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`COMPILE_DEFINITIONS`
+property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.
The following arguments specify compile definitions. Repeated calls for the
same ``<target>`` append items in the order called.
diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst
index e45b209ad..0d86c91e6 100644
--- a/Help/command/target_compile_options.rst
+++ b/Help/command/target_compile_options.rst
@@ -22,9 +22,9 @@ If ``BEFORE`` is specified, the content will be prepended to the property
instead of being appended.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
-items will populate the :prop_tgt:`COMPILE_OPTIONS` property of
-``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+specify the :ref:`scope <Target Usage Requirements>` of the following arguments.
+``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`COMPILE_OPTIONS`
+property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.
The following arguments specify compile options. Repeated calls for the same
``<target>`` append items in the order called.
diff --git a/Help/command/target_include_directories.rst b/Help/command/target_include_directories.rst
index 9a99a7d2e..f13ff290a 100644
--- a/Help/command/target_include_directories.rst
+++ b/Help/command/target_include_directories.rst
@@ -18,9 +18,9 @@ By using ``AFTER`` or ``BEFORE`` explicitly, you can select between appending
and prepending, independent of the default.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to specify
-the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` items will
-populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``.
-``PUBLIC`` and ``INTERFACE`` items will populate the
+the :ref:`scope <Target Usage Requirements>` of the following arguments.
+``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`INCLUDE_DIRECTORIES`
+property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property of ``<target>``.
The following arguments specify include directories.
diff --git a/Help/command/target_link_directories.rst b/Help/command/target_link_directories.rst
index bb75a3de4..b72f74606 100644
--- a/Help/command/target_link_directories.rst
+++ b/Help/command/target_link_directories.rst
@@ -21,11 +21,12 @@ The named ``<target>`` must have been created by a command such as
:ref:`ALIAS target <Alias Targets>`.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the items that follow them. ``PRIVATE`` and
-``PUBLIC`` items will populate the :prop_tgt:`LINK_DIRECTORIES` property
-of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_LINK_DIRECTORIES` property of ``<target>``
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items).
+specify the :ref:`scope <Target Usage Requirements>` of the items that follow
+them. ``PRIVATE`` and ``PUBLIC`` items will populate the
+:prop_tgt:`LINK_DIRECTORIES` property of ``<target>``. ``PUBLIC`` and
+``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_LINK_DIRECTORIES`
+property of ``<target>`` (:ref:`IMPORTED targets <Imported Targets>` only
+support ``INTERFACE`` items).
Each item specifies a link directory and will be converted to an absolute
path if necessary before adding it to the relevant property. Repeated
calls for the same ``<target>`` append items in the order called.
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index c85094aa9..bb7b5cc10 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -146,8 +146,10 @@ Libraries for a Target and/or its Dependents
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
-The ``PUBLIC``, ``PRIVATE`` and ``INTERFACE`` keywords can be used to
+The ``PUBLIC``, ``PRIVATE`` and ``INTERFACE``
+:ref:`scope <Target Usage Requirements>` keywords can be used to
specify both the link dependencies and the link interface in one command.
+
Libraries and targets following ``PUBLIC`` are linked to, and are made
part of the link interface. Libraries and targets following ``PRIVATE``
are linked to, but are not made part of the link interface. Libraries
diff --git a/Help/command/target_link_options.rst b/Help/command/target_link_options.rst
index 87dff39ae..3cd0e64e3 100644
--- a/Help/command/target_link_options.rst
+++ b/Help/command/target_link_options.rst
@@ -32,9 +32,9 @@ If ``BEFORE`` is specified, the content will be prepended to the property
instead of being appended.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
-items will populate the :prop_tgt:`LINK_OPTIONS` property of
-``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+specify the :ref:`scope <Target Usage Requirements>` of the following arguments.
+``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`LINK_OPTIONS`
+property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_LINK_OPTIONS` property of ``<target>``.
The following arguments specify link options. Repeated calls for the same
``<target>`` append items in the order called.
diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst
index 9f7dabbd4..84f5d1225 100644
--- a/Help/command/target_precompile_headers.rst
+++ b/Help/command/target_precompile_headers.rst
@@ -25,9 +25,9 @@ The named ``<target>`` must have been created by a command such as
:ref:`ALIAS target <Alias Targets>`.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
-items will populate the :prop_tgt:`PRECOMPILE_HEADERS` property of
-``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+specify the :ref:`scope <Target Usage Requirements>` of the following arguments.
+``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`PRECOMPILE_HEADERS`
+property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` property of ``<target>``
(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items).
Repeated calls for the same ``<target>`` will append items in the order called.
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index 72119f6a6..461175a16 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -22,10 +22,10 @@ The named ``<target>`` must have been created by a command such as
``<target>`` can be a custom target.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
-specify the scope of the source file paths (``<items>``) that follow
-them. ``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`SOURCES`
-property of ``<target>``, which are used when building the target itself.
-``PUBLIC`` and ``INTERFACE`` items will populate the
+specify the :ref:`scope <Target Usage Requirements>` of the source file paths
+(``<items>``) that follow them. ``PRIVATE`` and ``PUBLIC`` items will
+populate the :prop_tgt:`SOURCES` property of ``<target>``, which are used when
+building the target itself. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``, which are used
when building dependents. A target created by :command:`add_custom_target`
can only have ``PRIVATE`` scope.
@@ -75,9 +75,33 @@ File Sets
Adds a file set to a target, or adds files to an existing file set. Targets
have zero or more named file sets. Each file set has a name, a type, a scope of
``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and
-files within those directories. The only acceptable type is ``HEADERS``. The
-optional default file sets are named after their type. The target may not be a
-custom target or :prop_tgt:`FRAMEWORK` target.
+files within those directories. The acceptable types include:
+
+``HEADERS``
+
+ Sources intended to be used via a language's ``#include`` mechanism.
+
+``CXX_MODULES``
+
+ .. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Sources which contain C++ interface module or partition units (i.e., those
+ using the ``export`` keyword). This file set type may not have an
+ ``INTERFACE`` scope except on ``IMPORTED`` targets.
+
+``CXX_MODULE_HEADER_UNITS``
+
+ .. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ C++ header sources which may be imported by other C++ source code. This file
+ set type may not have an ``INTERFACE`` scope except on ``IMPORTED`` targets.
+
+The optional default file sets are named after their type. The target may not
+be a custom target or :prop_tgt:`FRAMEWORK` target.
Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for
the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets
@@ -93,16 +117,17 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o
The name of the file set to create or add to. It must contain only letters,
numbers and underscores. Names starting with a capital letter are reserved
- for built-in file sets predefined by CMake. The only predefined set name is
- ``HEADERS``. All other set names must not start with a capital letter or
+ for built-in file sets predefined by CMake. The only predefined set names
+ are those matching the acceptable types. All other set names must not start
+ with a capital letter or
underscore.
``TYPE <type>``
- Every file set is associated with a particular type of file. ``HEADERS``
- is currently the only defined type and it is an error to specify anything
- else. As a special case, if the name of the file set is ``HEADERS``, the
- type does not need to be specified and the ``TYPE <type>`` arguments can be
+ Every file set is associated with a particular type of file. Only types
+ specified above may be used and it is an error to specify anything else. As
+ a special case, if the name of the file set is one of the types, the type
+ does not need to be specified and the ``TYPE <type>`` arguments can be
omitted. For all other file set names, ``TYPE`` is required.
``BASE_DIRS <dirs>...``
@@ -134,6 +159,8 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o
The following target properties are set by ``target_sources(FILE_SET)``,
but they should not generally be manipulated directly:
+For file sets of type ``HEADERS``:
+
* :prop_tgt:`HEADER_SETS`
* :prop_tgt:`INTERFACE_HEADER_SETS`
* :prop_tgt:`HEADER_SET`
@@ -141,17 +168,37 @@ but they should not generally be manipulated directly:
* :prop_tgt:`HEADER_DIRS`
* :prop_tgt:`HEADER_DIRS_<NAME>`
+For file sets of type ``CXX_MODULES``:
+
+* :prop_tgt:`CXX_MODULE_SETS`
+* :prop_tgt:`INTERFACE_CXX_MODULE_SETS`
+* :prop_tgt:`CXX_MODULE_SET`
+* :prop_tgt:`CXX_MODULE_SET_<NAME>`
+* :prop_tgt:`CXX_MODULE_DIRS`
+* :prop_tgt:`CXX_MODULE_DIRS_<NAME>`
+
+For file sets of type ``CXX_MODULE_HEADER_UNITS``:
+
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS`
+* :prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>`
+
Target properties related to include directories are also modified by
``target_sources(FILE_SET)`` as follows:
:prop_tgt:`INCLUDE_DIRECTORIES`
- If the ``TYPE`` is ``HEADERS``, and the scope of the file set is ``PRIVATE``
- or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are wrapped in
- :genex:`$<BUILD_INTERFACE>` and appended to this property.
+ If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope
+ of the file set is ``PRIVATE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of
+ the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this
+ property.
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
- If the ``TYPE`` is ``HEADERS``, and the scope of the file set is
- ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are
- wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this property.
+ If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope
+ of the file set is ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of
+ the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this
+ property.
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index 806a98d4b..9e9f39fb4 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -14,10 +14,16 @@ Try Compiling Whole Projects
.. code-block:: cmake
- try_compile(<resultVar> <bindir> <srcdir>
- <projectName> [<targetName>] [CMAKE_FLAGS <flags>...]
+ try_compile(<resultVar> PROJECT <projectName>
+ SOURCE_DIR <srcdir>
+ [BINARY_DIR <bindir>]
+ [TARGET <targetName>]
+ [NO_CACHE]
+ [CMAKE_FLAGS <flags>...]
[OUTPUT_VARIABLE <var>])
+.. versionadded:: 3.25
+
Try building a project. The success or failure of the ``try_compile``,
i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``.
@@ -34,6 +40,17 @@ below for the meaning of other options.
Previously this was only done by the
:ref:`source file <Try Compiling Source Files>` signature.
+This command also supports an alternate signature
+which was present in older versions of CMake:
+
+.. code-block:: cmake
+
+ try_compile(<resultVar> <bindir> <srcdir>
+ <projectName> [<targetName>]
+ [NO_CACHE]
+ [CMAKE_FLAGS <flags>...]
+ [OUTPUT_VARIABLE <var>])
+
.. _`Try Compiling Source Files`:
Try Compiling Source Files
@@ -41,7 +58,12 @@ Try Compiling Source Files
.. code-block:: cmake
- try_compile(<resultVar> <bindir> <srcfile|SOURCES srcfile...>
+ try_compile(<resultVar>
+ <SOURCES <srcfile...> |
+ SOURCE_FROM_CONTENT <name> <content> |
+ SOURCE_FROM_VAR <name> <var> |
+ SOURCE_FROM_FILE <name> <path> >...
+ [NO_CACHE]
[CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
@@ -53,15 +75,19 @@ Try Compiling Source Files
[<LANG>_EXTENSIONS <bool>]
)
+.. versionadded:: 3.25
+
Try building an executable or static library from one or more source files
(which one is determined by the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE`
variable). The success or failure of the ``try_compile``, i.e. ``TRUE`` or
``FALSE`` respectively, is returned in ``<resultVar>``.
-In this form, one or more source files must be provided. If
-:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to ``EXECUTABLE``,
-the sources must include a definition for ``main`` and CMake will create a
-``CMakeLists.txt`` file to build the source(s) as an executable.
+In this form, one or more source files must be provided. Additionally, one of
+``SOURCES`` and/or ``SOURCE_FROM_*`` must precede other keywords.
+
+If :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to
+``EXECUTABLE``, the sources must include a definition for ``main`` and CMake
+will create a ``CMakeLists.txt`` file to build the source(s) as an executable.
If :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``STATIC_LIBRARY``,
a static library will be built instead and no definition for ``main`` is
required. For an executable, the generated ``CMakeLists.txt`` file would
@@ -76,11 +102,45 @@ contain something like the following:
target_link_options(cmTryCompileExec PRIVATE <LINK_OPTIONS from caller>)
target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})
+CMake automatically generates, for each ``try_compile`` operation, a
+unique directory under ``${CMAKE_BINARY_DIR}/CMakeFiles/CMakeScratch``
+with an unspecified name. These directories are cleaned automatically unless
+:option:`--debug-trycompile <cmake --debug-trycompile>` is passed to ``cmake``.
+Such directories from previous runs are also unconditionally cleaned at the
+beginning of any ``cmake`` execution.
+
+This command also supports an alternate signature
+which was present in older versions of CMake:
+
+.. code-block:: cmake
+
+ try_compile(<resultVar> <bindir> <srcfile|SOURCES srcfile...>
+ [NO_CACHE]
+ [CMAKE_FLAGS <flags>...]
+ [COMPILE_DEFINITIONS <defs>...]
+ [LINK_OPTIONS <options>...]
+ [LINK_LIBRARIES <libs>...]
+ [OUTPUT_VARIABLE <var>]
+ [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]]
+ [<LANG>_STANDARD <std>]
+ [<LANG>_STANDARD_REQUIRED <bool>]
+ [<LANG>_EXTENSIONS <bool>]
+ )
+
+In this version, ``try_compile`` will use ``<bindir>/CMakeFiles/CMakeTmp`` for
+its operation, and all such files will be cleaned automatically.
+For debugging, :option:`--debug-trycompile <cmake --debug-trycompile>` can be
+passed to ``cmake`` to avoid this clean. However, multiple sequential
+``try_compile`` operations, if given the same ``<bindir>``, will reuse this
+single output directory, such that you can only debug one such ``try_compile``
+call at a time. Use of the newer signature is recommended to simplify
+debugging of multiple ``try_compile`` operations.
+
The options are:
``CMAKE_FLAGS <flags>...``
- Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to
- the ``cmake`` command-line used to drive the test build.
+ Specify flags of the form :option:`-DVAR:TYPE=VALUE <cmake -D>` to be passed
+ to the :manual:`cmake(1)` command-line used to drive the test build.
The above example shows how values for variables
``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES``
are used.
@@ -111,9 +171,61 @@ The options are:
set the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property in the generated
project, depending on the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable.
+``NO_CACHE``
+ .. versionadded:: 3.25
+
+ The result will be stored in a normal variable rather than a cache entry.
+
+ The result variable is normally cached so that a simple pattern can be used
+ to avoid repeating the test on subsequent executions of CMake:
+
+ .. code-block:: cmake
+
+ if(NOT DEFINED RESULTVAR)
+ # ...(check-specific setup code)...
+ try_compile(RESULTVAR ...)
+ # ...(check-specific logging and cleanup code)...
+ endif()
+
+ If the guard variable and result variable are not the same (for example, if
+ the test is part of a larger inspection), ``NO_CACHE`` may be useful to avoid
+ leaking the intermediate result variable into the cache.
+
``OUTPUT_VARIABLE <var>``
Store the output from the build process in the given variable.
+``SOURCE_FROM_CONTENT <name> <content>``
+ .. versionadded:: 3.25
+
+ Write ``<content>`` to a file named ``<name>`` in the operation directory.
+ This can be used to bypass the need to separately write a source file when
+ the contents of the file are dynamically specified. The specified ``<name>``
+ is not allowed to contain path components.
+
+ ``SOURCE_FROM_CONTENT`` may be specified multiple times.
+
+``SOURCE_FROM_FILE <name> <path>``
+ .. versionadded:: 3.25
+
+ Copy ``<path>`` to a file named ``<name>`` in the operation directory. This
+ can be used to consolidate files into the operation directory, which may be
+ useful if a source which already exists (i.e. as a stand-alone file in a
+ project's source repository) needs to refer to other file(s) created by
+ ``SOURCE_FROM_*``. (Otherwise, ``SOURCES`` is usually more convenient.) The
+ specified ``<name>`` is not allowed to contain path components.
+
+``SOURCE_FROM_VAR <name> <var>``
+ .. versionadded:: 3.25
+
+ Write the contents of ``<var>`` to a file named ``<name>`` in the operation
+ directory. This is the same as ``SOURCE_FROM_CONTENT``, but takes the
+ contents from the specified CMake variable, rather than directly, which may
+ be useful when passing arguments through a function which wraps
+ ``try_compile``. The specified ``<name>`` is not allowed to contain path
+ components.
+
+ ``SOURCE_FROM_VAR`` may be specified multiple times.
+
``<LANG>_STANDARD <std>``
.. versionadded:: 3.8
@@ -136,17 +248,6 @@ The options are:
:prop_tgt:`OBJC_EXTENSIONS`, :prop_tgt:`OBJCXX_EXTENSIONS`,
or :prop_tgt:`CUDA_EXTENSIONS` target property of the generated project.
-In this version all files in ``<bindir>/CMakeFiles/CMakeTmp`` will be
-cleaned automatically. For debugging, ``--debug-trycompile`` can be
-passed to ``cmake`` to avoid this clean. However, multiple sequential
-``try_compile`` operations reuse this single output directory. If you use
-``--debug-trycompile``, you can only debug one ``try_compile`` call at a time.
-The recommended procedure is to protect all ``try_compile`` calls in your
-project by ``if(NOT DEFINED <resultVar>)`` logic, configure with cmake
-all the way through once, then delete the cache entry associated with
-the try_compile call of interest, and then re-run cmake again with
-``--debug-trycompile``.
-
Other Behavior Settings
^^^^^^^^^^^^^^^^^^^^^^^
@@ -214,9 +315,15 @@ a build configuration.
the generated project (unless overridden by an explicit option).
.. versionchanged:: 3.14
- For the :generator:`Green Hills MULTI` generator the GHS toolset and target
- system customization cache variables are also propagated into the test project.
+ For the :generator:`Green Hills MULTI` generator, the GHS toolset and target
+ system customization cache variables are also propagated into the test
+ project.
.. versionadded:: 3.24
The :variable:`CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES` variable may be
set to disable passing platform variables into the test project.
+
+.. versionadded:: 3.25
+ If :policy:`CMP0141` is set to ``NEW``, one can use
+ :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` to specify the MSVC debug
+ information format.
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index fc41cdd7b..cd41a4ba2 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -13,68 +13,99 @@ Try Compiling and Running Source Files
.. code-block:: cmake
try_run(<runResultVar> <compileResultVar>
- <bindir> <srcfile> [CMAKE_FLAGS <flags>...]
+ <SOURCES <srcfile...> |
+ SOURCE_FROM_CONTENT <name> <content> |
+ SOURCE_FROM_VAR <name> <var> |
+ SOURCE_FROM_FILE <name> <path> >...
+ [NO_CACHE]
+ [CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
[LINK_LIBRARIES <libs>...]
[COMPILE_OUTPUT_VARIABLE <var>]
+ [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]]
+ [<LANG>_STANDARD <std>]
+ [<LANG>_STANDARD_REQUIRED <bool>]
+ [<LANG>_EXTENSIONS <bool>]
[RUN_OUTPUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDOUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDERR_VARIABLE <var>]
[OUTPUT_VARIABLE <var>]
[WORKING_DIRECTORY <var>]
- [ARGS <args>...])
+ [ARGS <args>...]
+ )
+
+.. versionadded:: 3.25
Try compiling a ``<srcfile>``. Returns ``TRUE`` or ``FALSE`` for success
or failure in ``<compileResultVar>``. If the compile succeeded, runs the
executable and returns its exit code in ``<runResultVar>``. If the
executable was built, but failed to run, then ``<runResultVar>`` will be
set to ``FAILED_TO_RUN``. See the :command:`try_compile` command for
-information on how the test project is constructed to build the source file.
-
-The options are:
-
-``CMAKE_FLAGS <flags>...``
- Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to
- the ``cmake`` command-line used to drive the test build.
- The example in :command:`try_compile` shows how values for variables
- ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES``
- are used.
+documentation of options common to both commands, and for information on how
+the test project is constructed to build the source file.
-``COMPILE_DEFINITIONS <defs>...``
- Specify ``-Ddefinition`` arguments to pass to :command:`add_definitions`
- in the generated test project.
-
-``COMPILE_OUTPUT_VARIABLE <var>``
- Report the compile step build output in a given variable.
+One or more source files must be provided. Additionally, one of ``SOURCES``
+and/or ``SOURCE_FROM_*`` must precede other keywords.
-``LINK_LIBRARIES <libs>...``
- .. versionadded:: 3.2
+This command also supports an alternate signature
+which was present in older versions of CMake:
- Specify libraries to be linked in the generated project.
- The list of libraries may refer to system libraries and to
- :ref:`Imported Targets <Imported Targets>` from the calling project.
+.. code-block:: cmake
- If this option is specified, any ``-DLINK_LIBRARIES=...`` value
- given to the ``CMAKE_FLAGS`` option will be ignored.
+ try_run(<runResultVar> <compileResultVar>
+ <bindir> <srcfile|SOURCES srcfile...>
+ [NO_CACHE]
+ [CMAKE_FLAGS <flags>...]
+ [COMPILE_DEFINITIONS <defs>...]
+ [LINK_OPTIONS <options>...]
+ [LINK_LIBRARIES <libs>...]
+ [COMPILE_OUTPUT_VARIABLE <var>]
+ [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]]
+ [<LANG>_STANDARD <std>]
+ [<LANG>_STANDARD_REQUIRED <bool>]
+ [<LANG>_EXTENSIONS <bool>]
+ [RUN_OUTPUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDOUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDERR_VARIABLE <var>]
+ [OUTPUT_VARIABLE <var>]
+ [WORKING_DIRECTORY <var>]
+ [ARGS <args>...]
+ )
-``LINK_OPTIONS <options>...``
- .. versionadded:: 3.14
+The options specific to ``try_run`` are:
- Specify link step options to pass to :command:`target_link_options` in the
- generated project.
+``COMPILE_OUTPUT_VARIABLE <var>``
+ Report the compile step build output in a given variable.
``OUTPUT_VARIABLE <var>``
Report the compile build output and the output from running the executable
- in the given variable. This option exists for legacy reasons. Prefer
- ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead.
+ in the given variable. This option exists for legacy reasons and is only
+ supported by the old ``try_run`` signature.
+ Prefer ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead.
``RUN_OUTPUT_VARIABLE <var>``
Report the output from running the executable in a given variable.
+``RUN_OUTPUT_STDOUT_VARIABLE <var>``
+ .. versionadded:: 3.25
+
+ Report the output of stdout from running the executable in a given variable.
+
+``RUN_OUTPUT_STDERR_VARIABLE <var>``
+ .. versionadded:: 3.25
+
+ Report the output of stderr from running the executable in a given variable.
+
``WORKING_DIRECTORY <var>``
.. versionadded:: 3.20
Run the executable in the given directory. If no ``WORKING_DIRECTORY`` is
- specified, the executable will run in ``<bindir>``.
+ specified, the executable will run in ``<bindir>`` or the current build
+ directory.
+
+``ARGS <args>...``
+ Additional arguments to pass to the executable when running it.
Other Behavior Settings
^^^^^^^^^^^^^^^^^^^^^^^
@@ -110,6 +141,7 @@ These cache entries are:
In order to make cross compiling your project easier, use ``try_run``
only if really required. If you use ``try_run``, use the
+``RUN_OUTPUT_STDOUT_VARIABLE``, ``RUN_OUTPUT_STDERR_VARIABLE``,
``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really
required. Using them will require that when cross-compiling, the cache
variables will have to be set manually to the output of the executable.
diff --git a/Help/command/while.rst b/Help/command/while.rst
index a4957c1db..0bafae5ad 100644
--- a/Help/command/while.rst
+++ b/Help/command/while.rst
@@ -23,3 +23,11 @@ Per legacy, the :command:`endwhile` command admits
an optional ``<condition>`` argument.
If used, it must be a verbatim repeat of the argument of the opening
``while`` command.
+
+See Also
+^^^^^^^^
+
+ * :command:`break`
+ * :command:`continue`
+ * :command:`foreach`
+ * :command:`endwhile`
diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst
index a77b615b9..9df3cc45e 100644
--- a/Help/cpack_gen/archive.rst
+++ b/Help/cpack_gen/archive.rst
@@ -57,6 +57,12 @@ Variables specific to CPack Archive generator
.. versionadded:: 3.9
Per-component ``CPACK_ARCHIVE_<component>_FILE_NAME`` variables.
+.. variable:: CPACK_ARCHIVE_FILE_EXTENSION
+
+ .. versionadded:: 3.25
+
+ Package file extension. Default values are given in the list above.
+
.. variable:: CPACK_ARCHIVE_COMPONENT_INSTALL
Enable component packaging. If enabled (ON), then the archive generator
diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index f96ca3203..1514dbc69 100644
--- a/Help/cpack_gen/deb.rst
+++ b/Help/cpack_gen/deb.rst
@@ -57,7 +57,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.5
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_NAME`` variables.
- See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+ See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-source
.. variable:: CPACK_DEBIAN_FILE_NAME
CPACK_DEBIAN_<COMPONENT>_FILE_NAME
@@ -399,7 +399,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.4
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS`` variables.
- See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_ENHANCES
CPACK_DEBIAN_<COMPONENT>_PACKAGE_ENHANCES
@@ -419,7 +419,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.4
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_ENHANCES`` variables.
- See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_BREAKS
CPACK_DEBIAN_<COMPONENT>_PACKAGE_BREAKS
@@ -508,7 +508,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.4
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_REPLACES`` variables.
- See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_RECOMMENDS
CPACK_DEBIAN_<COMPONENT>_PACKAGE_RECOMMENDS
@@ -527,7 +527,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.4
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_RECOMMENDS`` variables.
- See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_SUGGESTS
CPACK_DEBIAN_<COMPONENT>_PACKAGE_SUGGESTS
@@ -545,7 +545,7 @@ List of CPack DEB generator specific variables:
.. versionadded:: 3.4
Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_SUGGESTS`` variables.
- See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS
@@ -639,7 +639,7 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_SOURCE` for component-based
installations.
- See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+ See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-source
.. note::
diff --git a/Help/cpack_gen/external.rst b/Help/cpack_gen/external.rst
index 4c083f085..b51131999 100644
--- a/Help/cpack_gen/external.rst
+++ b/Help/cpack_gen/external.rst
@@ -207,8 +207,8 @@ following fields in the root:
set.
``buildConfig``
- The build configuration given to CPack with the ``-C`` option. Only present
- if this option is set.
+ The build configuration given to CPack with the :option:`cpack -C` option.
+ Only present if this option is set.
``defaultDirectoryPermissions``
The default directory permissions given in
diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst
index f429bc5fa..faf8c74ff 100644
--- a/Help/cpack_gen/freebsd.rst
+++ b/Help/cpack_gen/freebsd.rst
@@ -62,8 +62,6 @@ the RPM information (e.g. package license).
- :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
by CPack itself, if nothing else sets it explicitly).
- - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
- parameter for :command:`project`).
.. variable:: CPACK_FREEBSD_PACKAGE_DESCRIPTION
@@ -75,6 +73,10 @@ the RPM information (e.g. package license).
- :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already
for Debian packaging, so it is used as a fallback).
+ - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
+ by CPack itself, if nothing else sets it explicitly).
+ - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
+ parameter for :command:`project`).
.. variable:: CPACK_FREEBSD_PACKAGE_WWW
@@ -85,12 +87,12 @@ the RPM information (e.g. package license).
* Mandatory: YES
* Default:
- - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
- :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
+ - :variable:`CPACK_PACKAGE_HOMEPAGE_URL`, or if that is not set,
+ - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
for Debian packaging, so it is used as a fallback).
.. versionadded:: 3.12
- The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
+ The ``CPACK_PACKAGE_HOMEPAGE_URL`` variable.
.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
diff --git a/Help/cpack_gen/ifw.rst b/Help/cpack_gen/ifw.rst
index c23bab413..c252095be 100644
--- a/Help/cpack_gen/ifw.rst
+++ b/Help/cpack_gen/ifw.rst
@@ -14,7 +14,7 @@ Overview
This :manual:`cpack generator <cpack-generators(7)>` generates
configuration and meta information for the `Qt Installer Framework
-<http://doc.qt.io/qtinstallerframework/index.html>`_ (QtIFW),
+<https://doc.qt.io/qtinstallerframework/index.html>`_ (QtIFW),
and runs QtIFW tools to generate a Qt installer.
QtIFW provides tools and utilities to create installers for
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index 299cfece9..df306c28e 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -207,3 +207,34 @@ on Windows Nullsoft Scriptable Install System.
.. versionadded:: 3.22
If set, do not display the page containing the license during installation.
+
+.. variable:: CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS
+
+ .. versionadded:: 3.25
+
+ This variable is a :ref:`semicolon-separated list <CMake Language Lists>` of
+ arguments to prepend to the nsis script to run.
+ If the arguments do not start with a ``/`` or a ``-``, it will add one
+ automatically to the corresponding arguments.
+ The command that will be run is::
+
+ makensis.exe <preArgs>... "nsisFileName.nsi" <postArgs>...
+
+ where ``<preArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS``
+ and ``<postArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS``.
+
+
+.. variable:: CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS
+
+ .. versionadded:: 3.25
+
+ This variable is a :ref:`semicolon-separated list <CMake Language Lists>` of
+ arguments to append to the nsis script to run.
+ If the arguments do not start with a ``/`` or a ``-``, it will add one
+ automatically to the corresponding arguments.
+ The command that will be run is::
+
+ makensis.exe <preArgs>... "nsisFileName.nsi" <postArgs>...
+
+ where ``<preArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS``
+ and ``<postArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS``.
diff --git a/Help/cpack_gen/nuget.rst b/Help/cpack_gen/nuget.rst
index c980dd64c..3bf7f84f6 100644
--- a/Help/cpack_gen/nuget.rst
+++ b/Help/cpack_gen/nuget.rst
@@ -110,7 +110,7 @@ List of CPack NuGet generator specific variables:
.. deprecated:: 3.20
Use a local license file
(:variable:`CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME`)
- or a `(SPDX) license identifier`_
+ or a `SPDX license identifier`_
(:variable:`CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION`) instead.
An URL for the package's license, often shown in UI displays as well
@@ -124,7 +124,7 @@ List of CPack NuGet generator specific variables:
.. versionadded:: 3.20
- A Software Package Data Exchange `(SPDX) license identifier`_ such as
+ A Software Package Data Exchange `SPDX license identifier`_ such as
``MIT``, ``BSD-3-Clause``, or ``LGPL-3.0-or-later``. In the case of a
choice of licenses or more complex restrictions, compound license
expressions may be formed using boolean operators, for example
@@ -162,6 +162,14 @@ List of CPack NuGet generator specific variables:
* Mandatory : NO
* Default : -
+.. variable:: CPACK_NUGET_PACKAGE_REQUIRE_LICENSE_ACCEPTANCE
+
+ When set to a true value, the user will be prompted to accept the license
+ before installing the package.
+
+ * Mandatory : NO
+ * Default : -
+
.. variable:: CPACK_NUGET_PACKAGE_ICON
CPACK_NUGET_<compName>_PACKAGE_ICON
@@ -247,9 +255,9 @@ List of CPack NuGet generator specific variables:
* Default : OFF
-.. _nuget.org: http://nuget.org
-.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
-.. _(SPDX) license identifier: https://spdx.org/licenses/
-.. _SPDX specification: https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
+.. _nuget.org: https://www.nuget.org
+.. _version specification: https://learn.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges
+.. _SPDX license identifier: https://spdx.github.io/spdx-spec/SPDX-license-list
+.. _SPDX specification: https://spdx.github.io/spdx-spec/SPDX-license-expressions
.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst
index 0d287fc91..b1e0077bf 100644
--- a/Help/cpack_gen/rpm.rst
+++ b/Help/cpack_gen/rpm.rst
@@ -18,7 +18,7 @@ The CPack RPM generator has specific features which are controlled by the specif
**grouping name** written in upper case. It may be either a component name or
a component GROUP name. Usually those variables correspond to RPM spec file
entities. One may find information about spec files here
-http://www.rpm.org/wiki/Docs
+https://rpm.org/documentation
.. versionchanged:: 3.6
@@ -972,7 +972,7 @@ For CMake projects SRPM package would be produced by executing::
Produced SRPM package is expected to be built with :manual:`cmake(1)` executable
and packaged with :manual:`cpack(1)` executable so CMakeLists.txt has to be
located in root source directory and must be able to generate binary rpm
- packages by executing ``cpack -G`` command. The two executables as well as
+ packages by executing :option:`cpack -G` command. The two executables as well as
rpmbuild must also be present when generating binary rpm packages from the
produced SRPM package.
diff --git a/Help/cpack_gen/wix.rst b/Help/cpack_gen/wix.rst
index a3d43fc5f..c88004932 100644
--- a/Help/cpack_gen/wix.rst
+++ b/Help/cpack_gen/wix.rst
@@ -111,7 +111,7 @@ Windows using WiX.
simply provide the name of the culture. If you specify more than one
culture identifier in a comma or semicolon delimited list, the first one
that is found will be used. You can find a list of supported languages at:
- http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm
+ https://wixtoolset.org//documentation/manual/v3/wixui/wixui_localization.html
.. variable:: CPACK_WIX_TEMPLATE
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index 7638d2210..336137f5f 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -7,6 +7,23 @@ See documentation on `CMake Development`_ for more information.
.. _`CMake Development`: README.rst
+Features are gated behind ``CMAKE_EXPERIMENTAL_`` variables which must be set
+to specific values in order to enable their gated behaviors. Note that the
+specific values will change over time to reinforce their experimental nature.
+When used, a warning will be generated to indicate that an experimental
+feature is in use and that the affected behavior in the project is not part of
+CMake's stability guarantees.
+
+C++20 Module APIs
+=================
+
+Variable: ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+Value: ``3c375311-a3c9-4396-a187-3227ef642046``
+
+In order to support C++20 modules, there are a number of behaviors that have
+CMake APIs to provide the required features to build and export them from a
+project.
+
C++20 Module Dependencies
=========================
@@ -22,6 +39,10 @@ they can use it to develop and test their dependency scanning tool.
The ``CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE`` variable must also be set
to tell CMake how to invoke the C++20 module dependency scanning tool.
+MSVC 19.34 (provided with Visual Studio 17.4) and above contains the support
+that CMake needs and has these variables already set up as required and only
+the UUID variable needs to be set.
+
For example, add code like the following to a test project:
.. code-block:: cmake
@@ -40,13 +61,8 @@ dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder. The
``CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT`` file may be set to ``msvc``
for scandep rules which use ``msvc``-style dependency reporting.
-For tools which need to know the file set the source belongs to, the
-``CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_<FILE_SET_TYPE>`` flag may
-be provided so that different source types can be distinguished prior to
-scanning.
-
The module dependencies should be written in the format described
-by the `P1689r4`_ paper.
+by the `P1689r5`_ paper.
Compiler writers may try out their scanning functionality using
the `cxx-modules-sandbox`_ test project, modified to set variables
@@ -73,5 +89,5 @@ the GCC documentation, but the relevant section for the purposes of CMake is:
-- GCC module mapper documentation
.. _`D1483r1`: https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html
-.. _`P1689r4`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1689r4.html
+.. _`P1689r5`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html
.. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox
diff --git a/Help/envvar/ASM_DIALECTFLAGS.rst b/Help/envvar/ASM_DIALECTFLAGS.rst
index 2e1c6d294..2af4b5857 100644
--- a/Help/envvar/ASM_DIALECTFLAGS.rst
+++ b/Help/envvar/ASM_DIALECTFLAGS.rst
@@ -3,13 +3,16 @@ ASM<DIALECT>FLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling a specific dialect of an
-assembly language. ``ASM<DIALECT>FLAGS`` can be ``ASMFLAGS``, ``ASM_NASMFLAGS``,
-``ASM_MASMFLAGS`` or ``ASM-ATTFLAGS``. Will only be used by CMake on the
-first configuration to determine ``ASM_<DIALECT>`` default compilation
-flags, after which the value for ``ASM<DIALECT>FLAGS`` is stored in the cache
-as ``CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>``. For any configuration
-run (including the first), the environment variable will be ignored, if the
-``CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>`` variable is defined.
+Add default compilation flags to be used when compiling a specific dialect
+of an assembly language. ``ASM<DIALECT>FLAGS`` can be one of:
+
+* ``ASMFLAGS``
+* ``ASM_NASMFLAGS``
+* ``ASM_MASMFLAGS``
+* ``ASM-ATTFLAGS``
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``ASM<DIALECT>``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_ASM<DIALECT>_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/CFLAGS.rst b/Help/envvar/CFLAGS.rst
index 190b4f47c..a6b245207 100644
--- a/Help/envvar/CFLAGS.rst
+++ b/Help/envvar/CFLAGS.rst
@@ -3,11 +3,10 @@ CFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``C`` files. Will only be
-used by CMake on the first configuration to determine ``CC`` default compilation
-flags, after which the value for ``CFLAGS`` is stored in the cache
-as :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration run
-(including the first), the environment variable will be ignored if the
-:variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``C`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``C``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_C_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/CMAKE_GENERATOR.rst b/Help/envvar/CMAKE_GENERATOR.rst
index 3488b040a..596e8f39e 100644
--- a/Help/envvar/CMAKE_GENERATOR.rst
+++ b/Help/envvar/CMAKE_GENERATOR.rst
@@ -6,9 +6,9 @@ CMAKE_GENERATOR
.. include:: ENV_VAR.txt
Specifies the CMake default generator to use when no generator is supplied
-with ``-G``. If the provided value doesn't name a generator known by CMake,
-the internal default is used. Either way the resulting generator selection
-is stored in the :variable:`CMAKE_GENERATOR` variable.
+with :option:`-G <cmake -G>`. If the provided value doesn't name a generator
+known by CMake, the internal default is used. Either way the resulting
+generator selection is stored in the :variable:`CMAKE_GENERATOR` variable.
Some generators may be additionally configured using the environment
variables:
diff --git a/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst
index b039845b1..e657904a0 100644
--- a/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst
+++ b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst
@@ -6,5 +6,5 @@ CMAKE_GENERATOR_PLATFORM
.. include:: ENV_VAR.txt
Default value for :variable:`CMAKE_GENERATOR_PLATFORM` if no Cache entry
-is present and no value is specified by :manual:`cmake(1)` ``-A`` option.
+is present and no value is specified by :option:`cmake -A` option.
This value is only applied if :envvar:`CMAKE_GENERATOR` is set.
diff --git a/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst
index 394dd88d1..03208e70c 100644
--- a/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst
+++ b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst
@@ -6,5 +6,5 @@ CMAKE_GENERATOR_TOOLSET
.. include:: ENV_VAR.txt
Default value for :variable:`CMAKE_GENERATOR_TOOLSET` if no Cache entry
-is present and no value is specified by :manual:`cmake(1)` ``-T`` option.
+is present and no value is specified by :option:`cmake -T` option.
This value is only applied if :envvar:`CMAKE_GENERATOR` is set.
diff --git a/Help/envvar/CSFLAGS.rst b/Help/envvar/CSFLAGS.rst
index 784328a73..6e909fe4b 100644
--- a/Help/envvar/CSFLAGS.rst
+++ b/Help/envvar/CSFLAGS.rst
@@ -5,11 +5,10 @@ CSFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``CSharp`` files. Will only be
-used by CMake on the first configuration to determine ``CSharp`` default
-compilation flags, after which the value for ``CSFLAGS`` is stored in the cache
-as :variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration
-run (including the first), the environment variable will be ignored if the
-:variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``CSharp`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``CSharp``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_CSharp_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/CTEST_PROGRESS_OUTPUT.rst b/Help/envvar/CTEST_PROGRESS_OUTPUT.rst
index 8c29d7d16..348acc689 100644
--- a/Help/envvar/CTEST_PROGRESS_OUTPUT.rst
+++ b/Help/envvar/CTEST_PROGRESS_OUTPUT.rst
@@ -14,5 +14,5 @@ variable is not set or has a value that evaluates to false, output is reported
normally with each test having its own start and end lines logged to the
output.
-The ``--progress`` option to :manual:`ctest <ctest(1)>` overrides this
-environment variable if both are given.
+The :option:`--progress <ctest --progress>` option to :manual:`ctest <ctest(1)>`
+overrides this environment variable if both are given.
diff --git a/Help/envvar/CUDAFLAGS.rst b/Help/envvar/CUDAFLAGS.rst
index af577a0a6..46a91df86 100644
--- a/Help/envvar/CUDAFLAGS.rst
+++ b/Help/envvar/CUDAFLAGS.rst
@@ -5,11 +5,10 @@ CUDAFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``CUDA`` files. Will only be
-used by CMake on the first configuration to determine ``CUDA`` default
-compilation flags, after which the value for ``CUDAFLAGS`` is stored in the
-cache as :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration
-run (including the first), the environment variable will be ignored if
-the :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``CUDA`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``CUDA``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_CUDA_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/CXXFLAGS.rst b/Help/envvar/CXXFLAGS.rst
index 460a347c5..f67431f0a 100644
--- a/Help/envvar/CXXFLAGS.rst
+++ b/Help/envvar/CXXFLAGS.rst
@@ -3,11 +3,10 @@ CXXFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``CXX`` (C++) files. Will
-only be used by CMake on the first configuration to determine ``CXX`` default
-compilation flags, after which the value for ``CXXFLAGS`` is stored in the cache
-as :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration run (
-including the first), the environment variable will be ignored if
-the :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``CXX`` (C++) files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``CXX``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_CXX_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/DESTDIR.rst b/Help/envvar/DESTDIR.rst
index 94cae4a81..dec843035 100644
--- a/Help/envvar/DESTDIR.rst
+++ b/Help/envvar/DESTDIR.rst
@@ -20,8 +20,9 @@ The packaging tool may then construct the package from the content of the
See the :variable:`CMAKE_INSTALL_PREFIX` variable to control the
installation prefix when configuring a build tree. Or, when using
-the :manual:`cmake(1)` command-line tool's ``--install`` mode,
-one may specify a different prefix using the ``--prefix`` option.
+the :manual:`cmake(1)` command-line tool's :option:`--install <cmake --install>`
+mode, one may specify a different prefix using the
+:option:`--prefix <cmake--install --prefix>` option.
.. note::
diff --git a/Help/envvar/FFLAGS.rst b/Help/envvar/FFLAGS.rst
index 53bffb67f..23bc8d264 100644
--- a/Help/envvar/FFLAGS.rst
+++ b/Help/envvar/FFLAGS.rst
@@ -3,11 +3,10 @@ FFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``Fortran`` files. Will only
-be used by CMake on the first configuration to determine ``Fortran`` default
-compilation flags, after which the value for ``FFLAGS`` is stored in the cache
-as :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration
-run (including the first), the environment variable will be ignored if
-the :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``Fortran`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``Fortran``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_Fortran_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/HIPFLAGS.rst b/Help/envvar/HIPFLAGS.rst
index 0df3416e2..31e239053 100644
--- a/Help/envvar/HIPFLAGS.rst
+++ b/Help/envvar/HIPFLAGS.rst
@@ -5,11 +5,10 @@ HIPFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``HIP`` files. Will only be
-used by CMake on the first configuration to determine ``HIP`` default
-compilation flags, after which the value for ``HIPFLAGS`` is stored in the
-cache as :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration
-run (including the first), the environment variable will be ignored if
-the :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``HIP`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``HIP``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_HIP_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/ISPCFLAGS.rst b/Help/envvar/ISPCFLAGS.rst
index 21df03775..b7a2bd595 100644
--- a/Help/envvar/ISPCFLAGS.rst
+++ b/Help/envvar/ISPCFLAGS.rst
@@ -5,11 +5,10 @@ ISPCFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``ISPC`` files. Will only be
-used by CMake on the first configuration to determine ``ISPC`` default
-compilation flags, after which the value for ``ISPCFLAGS`` is stored in the
-cache as :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration
-run (including the first), the environment variable will be ignored if
-the :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``ISPC`` files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``ISPC``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_ISPC_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/LANG_FLAGS.txt b/Help/envvar/LANG_FLAGS.txt
new file mode 100644
index 000000000..d01a56d2f
--- /dev/null
+++ b/Help/envvar/LANG_FLAGS.txt
@@ -0,0 +1,6 @@
+CMake uses this environment variable value, in combination with its own
+builtin default flags for the toolchain, to initialize and store the
+|CMAKE_LANG_FLAGS| cache entry.
+This occurs the first time a build tree is configured for language |LANG|.
+For any configuration run (including the first), the environment variable
+will be ignored if the |CMAKE_LANG_FLAGS| variable is already defined.
diff --git a/Help/envvar/RCFLAGS.rst b/Help/envvar/RCFLAGS.rst
index bc43cb212..7df83a72c 100644
--- a/Help/envvar/RCFLAGS.rst
+++ b/Help/envvar/RCFLAGS.rst
@@ -3,11 +3,10 @@ RCFLAGS
.. include:: ENV_VAR.txt
-Default compilation flags to be used when compiling ``resource`` files. Will
-only be used by CMake on the first configuration to determine ``resource``
-default compilation flags, after which the value for ``RCFLAGS`` is stored in
-the cache as :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>`. For any
-configuration run (including the first), the environment variable will be ignored
-if the :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined.
+Add default compilation flags to be used when compiling ``RC`` (resource) files.
+
+.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>`
+.. |LANG| replace:: ``RC``
+.. include:: LANG_FLAGS.txt
See also :variable:`CMAKE_RC_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/envvar/SSL_CERT_DIR.rst b/Help/envvar/SSL_CERT_DIR.rst
new file mode 100644
index 000000000..1e678e442
--- /dev/null
+++ b/Help/envvar/SSL_CERT_DIR.rst
@@ -0,0 +1,9 @@
+SSL_CERT_DIR
+------------
+
+.. versionadded:: 3.25
+
+.. include:: ENV_VAR.txt
+
+Specify default directory containing CA certificates. It overrides
+the default CA directory used.
diff --git a/Help/envvar/SSL_CERT_FILE.rst b/Help/envvar/SSL_CERT_FILE.rst
new file mode 100644
index 000000000..23216c094
--- /dev/null
+++ b/Help/envvar/SSL_CERT_FILE.rst
@@ -0,0 +1,9 @@
+SSL_CERT_FILE
+-------------
+
+.. versionadded:: 3.25
+
+.. include:: ENV_VAR.txt
+
+Specify the file name containing CA certificates. It overrides the
+default, os-specific CA file used.
diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst
index 1b4739b57..7a5993a85 100644
--- a/Help/generator/Green Hills MULTI.rst
+++ b/Help/generator/Green Hills MULTI.rst
@@ -28,12 +28,12 @@ Otherwise the ``primaryTarget`` will be composed from the values of :variable:`C
and ``GHS_TARGET_PLATFORM``. Defaulting to the value of ``arm_integrity.tgt``
* The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
- via the :manual:`cmake(1)` ``-A`` option.
+ via the :option:`cmake -A` option.
| Typical values of ``arm``, ``ppc``, ``86``, etcetera, are used.
-* The variable ``GHS_TARGET_PLATFORM`` may be set, perhaps via the :manual:`cmake(1)`
- ``-D`` option.
+* The variable ``GHS_TARGET_PLATFORM`` may be set, perhaps via the :option:`cmake -D`
+ option.
| Defaults to ``integrity``.
| Usual values are ``integrity``, ``threadx``, ``uvelosity``, ``velosity``,
@@ -55,11 +55,11 @@ The generator searches for the latest compiler or can be given a location to use
``GHS_TOOLSET_ROOT`` is the directory that is checked for the latest compiler.
* The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
- via the :manual:`cmake(1)` ``-T`` option, to specify the location of the toolset.
+ via the :option:`cmake -T` option, to specify the location of the toolset.
Both absolute and relative paths are valid. Paths are relative to ``GHS_TOOLSET_ROOT``.
-* The variable ``GHS_TOOLSET_ROOT`` may be set, perhaps via the :manual:`cmake(1)`
- ``-D`` option.
+* The variable ``GHS_TOOLSET_ROOT`` may be set, perhaps via the :option:`cmake -D`
+ option.
| Root path for toolset searches and relative paths.
| Defaults to ``C:/ghs`` in Windows or ``/usr/ghs`` in Linux.
diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst
index e5ce4f5cd..2cf823ac3 100644
--- a/Help/generator/Ninja Multi-Config.rst
+++ b/Help/generator/Ninja Multi-Config.rst
@@ -20,8 +20,8 @@ are intended to be run with ``ninja -f build-<Config>.ninja``. A
:variable:`CMAKE_CONFIGURATION_TYPES`.
``cmake --build . --config <Config>`` will always use ``build-<Config>.ninja``
-to build. If no ``--config`` argument is specified, ``cmake --build .`` will
-use ``build.ninja``.
+to build. If no :option:`--config <cmake--build --config>` argument is
+specified, :option:`cmake --build . <cmake --build>` will use ``build.ninja``.
Each ``build-<Config>.ninja`` file contains ``<target>`` targets as well as
``<target>:<Config>`` targets, where ``<Config>`` is the same as the
diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst
index 9ec33c354..888164f3c 100644
--- a/Help/generator/Visual Studio 10 2010.rst
+++ b/Help/generator/Visual Studio 10 2010.rst
@@ -1,52 +1,8 @@
Visual Studio 10 2010
---------------------
-Deprecated. Generates Visual Studio 10 (VS 2010) project files.
-
-.. note::
- This generator is deprecated and will be removed in a future version
- of CMake. It will still be possible to build with VS 10 2010 tools
- using the :generator:`Visual Studio 11 2012` (or above) generator
- with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v100``, or by
- using the :generator:`NMake Makefiles` generator.
-
-For compatibility with CMake versions prior to 3.0, one may specify this
-generator using the name ``Visual Studio 10`` without the year component.
-
-Project Types
-^^^^^^^^^^^^^
-
-Only Visual C++ and C# projects may be generated (and Fortran with
-Intel compiler integration). Other types of projects (Database,
-Website, etc.) are not supported.
-
-Platform Selection
-^^^^^^^^^^^^^^^^^^
-
-The default target platform name (architecture) is ``Win32``.
-
-.. versionadded:: 3.1
- The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
- via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
- name (architecture). For example:
-
- * ``cmake -G "Visual Studio 10 2010" -A Win32``
- * ``cmake -G "Visual Studio 10 2010" -A x64``
- * ``cmake -G "Visual Studio 10 2010" -A Itanium``
-
-For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of the generator name.
-This is supported only for:
-
-``Visual Studio 10 2010 Win64``
- Specify target platform ``x64``.
-
-``Visual Studio 10 2010 IA64``
- Specify target platform ``Itanium``.
-
-Toolset Selection
-^^^^^^^^^^^^^^^^^
-
-The ``v100`` toolset that comes with Visual Studio 10 2010 is selected by
-default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+Removed. This once generated Visual Studio 10 2010 project files, but
+the generator has been removed since CMake 3.25. It is still possible
+to build with VS 10 2010 tools using the :generator:`Visual Studio 12 2013`
+(or above) generator with :variable:`CMAKE_GENERATOR_TOOLSET` set to
+``v100``, or by using the :generator:`NMake Makefiles` generator.
diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst
index 3952228fe..4e7195c66 100644
--- a/Help/generator/Visual Studio 11 2012.rst
+++ b/Help/generator/Visual Studio 11 2012.rst
@@ -1,7 +1,14 @@
Visual Studio 11 2012
---------------------
-Generates Visual Studio 11 (VS 2012) project files.
+Deprecated. Generates Visual Studio 11 (VS 2012) project files.
+
+.. note::
+ This generator is deprecated and will be removed in a future version
+ of CMake. It will still be possible to build with VS 11 2012 tools
+ using the :generator:`Visual Studio 12 2013` (or above) generator
+ with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v110``, or by
+ using the :generator:`NMake Makefiles` generator.
For compatibility with CMake versions prior to 3.0, one may specify this
generator using the name "Visual Studio 11" without the year component.
@@ -20,7 +27,7 @@ The default target platform name (architecture) is ``Win32``.
.. versionadded:: 3.1
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
- via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 11 2012" -A Win32``
@@ -47,4 +54,4 @@ Toolset Selection
The ``v110`` toolset that comes with Visual Studio 11 2012 is selected by
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst
index 54a4d7eb9..3dbcfe65d 100644
--- a/Help/generator/Visual Studio 12 2013.rst
+++ b/Help/generator/Visual Studio 12 2013.rst
@@ -20,7 +20,7 @@ The default target platform name (architecture) is ``Win32``.
.. versionadded:: 3.1
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
- via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 12 2013" -A Win32``
@@ -42,7 +42,7 @@ Toolset Selection
The ``v120`` toolset that comes with Visual Studio 12 2013 is selected by
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
By default this generator uses the 32-bit variant even on a 64-bit host.
diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst
index d704ab271..af7dfaaa8 100644
--- a/Help/generator/Visual Studio 14 2015.rst
+++ b/Help/generator/Visual Studio 14 2015.rst
@@ -18,7 +18,7 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 14 2015" -A Win32``
@@ -40,7 +40,7 @@ Toolset Selection
The ``v140`` toolset that comes with Visual Studio 14 2015 is selected by
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
By default this generator uses the 32-bit variant even on a 64-bit host.
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index 912afade0..6bcc03384 100644
--- a/Help/generator/Visual Studio 15 2017.rst
+++ b/Help/generator/Visual Studio 15 2017.rst
@@ -26,7 +26,7 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 15 2017" -A Win32``
@@ -49,7 +49,7 @@ Toolset Selection
The ``v141`` toolset that comes with Visual Studio 15 2017 is selected by
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
By default this generator uses the 32-bit variant even on a 64-bit host.
diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst
index 6cefe6dbb..2918a6e58 100644
--- a/Help/generator/Visual Studio 16 2019.rst
+++ b/Help/generator/Visual Studio 16 2019.rst
@@ -25,7 +25,7 @@ The default target platform name (architecture) is that of the host
and is provided in the :variable:`CMAKE_VS_PLATFORM_NAME_DEFAULT` variable.
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 16 2019" -A Win32``
@@ -38,7 +38,7 @@ Toolset Selection
The ``v142`` toolset that comes with Visual Studio 16 2019 is selected by
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
By default this generator uses the 64-bit variant on x64 hosts and
diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst
index edf9d6031..ab101ac41 100644
--- a/Help/generator/Visual Studio 17 2022.rst
+++ b/Help/generator/Visual Studio 17 2022.rst
@@ -25,7 +25,7 @@ The default target platform name (architecture) is that of the host
and is provided in the :variable:`CMAKE_VS_PLATFORM_NAME_DEFAULT` variable.
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 17 2022" -A Win32``
@@ -38,7 +38,7 @@ Toolset Selection
The ``v143`` toolset that comes with VS 17 2022 is selected by default.
The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
By default this generator uses the 64-bit variant on x64 hosts and
diff --git a/Help/generator/Visual Studio 9 2008.rst b/Help/generator/Visual Studio 9 2008.rst
index 644f9363a..34349560e 100644
--- a/Help/generator/Visual Studio 9 2008.rst
+++ b/Help/generator/Visual Studio 9 2008.rst
@@ -10,7 +10,7 @@ The default target platform name (architecture) is ``Win32``.
.. versionadded:: 3.1
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
- via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ via the :option:`cmake -A` option, to specify a target platform
name (architecture). For example:
* ``cmake -G "Visual Studio 9 2008" -A Win32``
diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst
index e4900a1e0..9dd50155c 100644
--- a/Help/generator/Xcode.rst
+++ b/Help/generator/Xcode.rst
@@ -13,7 +13,7 @@ Toolset and Build System Selection
By default Xcode is allowed to select its own default toolchain.
The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
-via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+via the :option:`cmake -T` option, to specify another toolset.
.. versionadded:: 3.19
This generator supports toolset specification using one of these forms:
@@ -34,7 +34,7 @@ Supported pairs are:
See the :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable for allowed values.
For example, to select the original build system under Xcode 12,
- run :manual:`cmake(1)` with the option ``-T buildsystem=1``.
+ run :manual:`cmake(1)` with the option :option:`-T buildsystem=1 <cmake -T>`.
Swift Support
^^^^^^^^^^^^^
@@ -44,3 +44,13 @@ Swift Support
When using the :generator:`Xcode` generator with Xcode 6.1 or higher,
one may enable the ``Swift`` language with the :command:`enable_language`
command or the :command:`project`.
+
+Limitations
+^^^^^^^^^^^
+
+The Xcode generator does not support per-configuration sources.
+Code like the following will result in a generation error:
+
+.. code-block:: cmake
+
+ add_executable(MyApp mymain-$<CONFIG>.cpp)
diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst
index 847348167..e198789c7 100644
--- a/Help/guide/ide-integration/index.rst
+++ b/Help/guide/ide-integration/index.rst
@@ -47,8 +47,9 @@ does, and present the user with the presets listed in the file. Users should be
able to see (and possibly edit) the CMake cache variables, environment
variables, and command line options that are defined for a given preset. The
IDE should then construct the list of appropriate :manual:`cmake(1)` command
-line arguments based on these settings, rather than using the ``--preset=``
-option directly. The ``--preset=`` option is intended only as a convenient
+line arguments based on these settings, rather than using the
+:option:`--preset= <cmake --preset>` option directly. The
+:option:`--preset= <cmake --preset>` option is intended only as a convenient
frontend for command line users, and should not be used by the IDE.
For example, if a preset named ``ninja`` specifies ``Ninja`` as the generator
@@ -66,10 +67,9 @@ run:
cmake -S /path/to/source -B /path/to/source/build -G Ninja
In cases where a preset contains lots of cache variables, and passing all of
-them as ``-D`` flags would cause the command line length limit of the platform
-to be exceeded, the IDE should instead construct a temporary cache script and
-pass it with the ``-C`` flag. See :ref:`CMake Options` for details on how the
-``-C`` flag is used.
+them as :option:`-D <cmake -D>` flags would cause the command line length limit
+of the platform to be exceeded, the IDE should instead construct a temporary
+cache script and pass it with the :option:`-C <cmake -C>` flag.
While reading, parsing, and evaluating the contents of ``CMakePresets.json`` is
straightforward, it is not trivial. In addition to the documentation, IDE
@@ -110,8 +110,9 @@ Building
If a Makefile or Ninja generator is used to generate the build tree, it is not
recommended to invoke ``make`` or ``ninja`` directly. Instead, it is
-recommended that the IDE invoke :manual:`cmake(1)` with the ``--build``
-argument, which will in turn invoke the appropriate build tool.
+recommended that the IDE invoke :manual:`cmake(1)` with the
+:option:`--build <cmake --build>` argument, which will in turn invoke the
+appropriate build tool.
If an IDE project generator is used, such as :generator:`Xcode` or one of the
Visual Studio generators, and the IDE understands the project format used, the
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst
index cf1ec0186..3dac68a80 100644
--- a/Help/guide/tutorial/A Basic Starting Point.rst
+++ b/Help/guide/tutorial/A Basic Starting Point.rst
@@ -1,34 +1,81 @@
Step 1: A Basic Starting Point
==============================
-The most basic project is an executable built from source code files.
-For simple projects, a three line ``CMakeLists.txt`` file is all that is
-required. This will be the starting point for our tutorial. Create a
-``CMakeLists.txt`` file in the ``Step1`` directory that looks like:
-
-.. code-block:: cmake
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-start
-
- cmake_minimum_required(VERSION 3.10)
+Where do I start with CMake? This step will provide an introduction to some of
+CMake's basic syntax, commands, and variables. As these concepts are
+introduced, we will work through three exercises and create a simple CMake
+project.
+
+Each exercise in this step will start with some background information. Then, a
+goal and list of helpful resources are provided. Each file in the
+``Files to Edit`` section is in the ``Step1`` directory and contains one or
+more ``TODO`` comments. Each ``TODO`` represents a line or two of code to
+change or add. The ``TODO`` s are intended to be completed in numerical order,
+first complete ``TODO 1`` then ``TODO 2``, etc. The ``Getting Started``
+section will give some helpful hints and guide you through the exercise. Then
+the ``Build and Run`` section will walk step-by-step through how to build and
+test the exercise. Finally, at the end of each exercise the intended solution
+is discussed.
+
+Also note that each step in the tutorial builds on the next. So, for example,
+the starting code for ``Step2`` is the complete solution to ``Step1``.
+
+Exercise 1 - Building a Basic Project
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The most basic CMake project is an executable built from a single source code
+file. For simple projects like this, a ``CMakeLists.txt`` file with three
+commands is all that is required.
+
+**Note:** Although upper, lower and mixed case commands are supported by CMake,
+lower case commands are preferred and will be used throughout the tutorial.
+
+Any project's top most CMakeLists.txt must start by specifying a minimum CMake
+version using the :command:`cmake_minimum_required` command. This establishes
+policy settings and ensures that the following CMake functions are run with a
+compatible version of CMake.
+
+To start a project, we use the :command:`project` command to set the project
+name. This call is required with every project and should be called soon after
+:command:`cmake_minimum_required`. As we will see later, this command can
+also be used to specify other project level information such as the language
+or version number.
+
+Finally, the :command:`add_executable` command tells CMake to create an
+executable using the specified source code files.
+
+Goal
+----
+
+Understand how to create a simple CMake project.
+
+Helpful Resources
+-----------------
+
+* :command:`add_executable`
+* :command:`cmake_minimum_required`
+* :command:`project`
+
+Files to Edit
+-------------
- # set the project name
- project(Tutorial)
+* ``CMakeLists.txt``
- # add the executable
- add_executable(Tutorial tutorial.cxx)
+Getting Started
+----------------
+The source code for ``tutorial.cxx`` is provided in the
+``Help/guide/tutorial/Step1`` directory and can be used to compute the square
+root of a number. This file does not need to be edited in this step.
-Note that this example uses lower case commands in the ``CMakeLists.txt`` file.
-Upper, lower, and mixed case commands are supported by CMake. The source
-code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be
-used to compute the square root of a number.
+In the same directory is a ``CMakeLists.txt`` file which you will complete.
+Start with ``TODO 1`` and work through ``TODO 3``.
Build and Run
-------------
-That's all that is needed - we can build and run our project now! First, run
-the :manual:`cmake <cmake(1)>` executable or the
+Once ``TODO 1`` through ``TODO 3`` have been completed, we are ready to build
+and run our project! First, run the :manual:`cmake <cmake(1)>` executable or the
:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
with your chosen build tool.
@@ -40,8 +87,9 @@ build directory:
mkdir Step1_build
-Next, navigate to the build directory and run CMake to configure the project
-and generate a native build system:
+Next, navigate to that build directory and run
+:manual:`cmake <cmake(1)>` to configure the project and generate a native build
+system:
.. code-block:: console
@@ -62,114 +110,352 @@ Finally, try to use the newly built ``Tutorial`` with these commands:
Tutorial 10
Tutorial
+Solution
+--------
-Adding a Version Number and Configured Header File
---------------------------------------------------
+As mentioned above, a three line ``CMakeLists.txt`` is all that we need to get
+up and running. The first line is to use :command:`cmake_minimum_required` to
+set the CMake version as follows:
-The first feature we will add is to provide our executable and project with a
-version number. While we could do this exclusively in the source code, using
-``CMakeLists.txt`` provides more flexibility.
+.. raw:: html
-First, modify the ``CMakeLists.txt`` file to use the :command:`project` command
-to set the project name and version number.
+ <details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step2/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-project-VERSION
+ :caption: TODO 1: CMakeLists.txt
+ :name: CMakeLists.txt-cmake_minimum_required
:language: cmake
- :end-before: # specify the C++ standard
+ :end-before: # set the project name and version
-Then, configure a header file to pass the version number to the source
-code:
+.. raw:: html
-.. literalinclude:: Step2/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-configure_file
- :language: cmake
- :start-after: # to the source code
- :end-before: # add the executable
+ </details>
+
+The next step to make a basic project is to use the :command:`project`
+command as follows to set the project name:
+
+.. raw:: html
+
+ <details><summary>TODO 2: Click to show/hide answer</summary>
+
+.. code-block:: cmake
+ :caption: TODO 2: CMakeLists.txt
+ :name: CMakeLists.txt-project
+
+ project(Tutorial)
+
+.. raw:: html
-Since the configured file will be written into the binary tree, we
-must add that directory to the list of paths to search for include
-files. Add the following lines to the end of the ``CMakeLists.txt`` file:
+ </details>
+
+The last command to call for a basic project is
+:command:`add_executable`. We call it as follows:
+
+.. raw:: html
+
+ <details><summary>TODO 3: Click to show/hide answer</summary>
.. literalinclude:: Step2/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-target_include_directories
+ :caption: TODO 3: CMakeLists.txt
+ :name: CMakeLists.txt-add_executable
:language: cmake
- :start-after: # so that we will find TutorialConfig.h
+ :start-after: # add the executable
+ :end-before: # TODO 9:
-Using your favorite editor, create ``TutorialConfig.h.in`` in the source
-directory with the following contents:
+.. raw:: html
-.. literalinclude:: Step2/TutorialConfig.h.in
- :caption: TutorialConfig.h.in
- :name: TutorialConfig.h.in
- :language: c++
+ </details>
-When CMake configures this header file the values for
-``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
-replaced.
+Exercise 2 - Specifying the C++ Standard
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Next modify ``tutorial.cxx`` to include the configured header file,
-``TutorialConfig.h``.
+CMake has some special variables that are either created behind the scenes or
+have meaning to CMake when set by project code. Many of these variables start
+with ``CMAKE_``. Avoid this naming convention when creating variables for your
+projects. Two of these special user settable variables are
+:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`.
+These may be used together to specify the C++ standard needed to build the
+project.
-Finally, let's print out the executable name and version number by updating
-``tutorial.cxx`` as follows:
+Goal
+----
-.. literalinclude:: Step2/tutorial.cxx
- :caption: tutorial.cxx
- :name: tutorial.cxx-print-version
- :language: c++
- :start-after: {
- :end-before: // convert input to double
+Add a feature that requires C++11.
+
+Helpful Resources
+-----------------
+
+* :variable:`CMAKE_CXX_STANDARD`
+* :variable:`CMAKE_CXX_STANDARD_REQUIRED`
+* :command:`set`
+
+Files to Edit
+-------------
-Specify the C++ Standard
--------------------------
+* ``CMakeLists.txt``
+* ``tutorial.cxx``
-Next let's add some C++11 features to our project by replacing ``atof`` with
-``std::stod`` in ``tutorial.cxx``. At the same time, remove
-``#include <cstdlib>``.
+Getting Started
+---------------
+
+Continue editing files in the ``Step1`` directory. Start with ``TODO 4`` and
+complete through ``TODO 6``.
+
+First, edit ``tutorial.cxx`` by adding a feature that requires C++11. Then
+update ``CMakeLists.txt`` to require C++11.
+
+Build and Run
+-------------
+
+Let's build our project again. Since we already created a build directory and
+ran CMake for Exercise 1, we can skip to the build step:
+
+.. code-block:: console
+
+ cd Step1_build
+ cmake --build .
+
+Now we can try to use the newly built ``Tutorial`` with same commands as
+before:
+
+.. code-block:: console
+
+ Tutorial 4294967296
+ Tutorial 10
+ Tutorial
+
+Solution
+--------
+
+We start by adding some C++11 features to our project by replacing
+``atof`` with ``std::stod`` in ``tutorial.cxx``. This looks like
+the following:
+
+.. raw:: html
+
+ <details><summary>TODO 4: Click to show/hide answer</summary>
.. literalinclude:: Step2/tutorial.cxx
- :caption: tutorial.cxx
+ :caption: TODO 4: tutorial.cxx
:name: tutorial.cxx-cxx11
:language: c++
:start-after: // convert input to double
- :end-before: // calculate square root
+ :end-before: // TODO 12:
+
+.. raw:: html
+
+ </details>
+
+To complete ``TODO 5``, simply remove ``#include <cstdlib>``.
We will need to explicitly state in the CMake code that it should use the
-correct flags. The easiest way to enable support for a specific C++ standard
-in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this
-tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the
-``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`
-to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the
-call to ``add_executable``.
+correct flags. One way to enable support for a specific C++ standard in CMake
+is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this tutorial, set
+the :variable:`CMAKE_CXX_STANDARD` variable in the ``CMakeLists.txt`` file to
+``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to ``True``. Make sure to
+add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to
+:command:`add_executable`.
+
+.. raw:: html
+
+ <details><summary>TODO 6: Click to show/hide answer</summary>
.. literalinclude:: Step2/CMakeLists.txt
- :caption: CMakeLists.txt
+ :caption: TODO 6: CMakeLists.txt
:name: CMakeLists.txt-CXX_STANDARD
:language: cmake
- :end-before: # configure a header file to pass some of the CMake settings
+ :start-after: # specify the C++ standard
+ :end-before: # TODO 7:
+
+.. raw:: html
-Rebuild
--------
+ </details>
-Let's build our project again. We already created a build directory and ran
-CMake, so we can skip to the build step:
+Exercise 3 - Adding a Version Number and Configured Header File
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes it may be useful to have a variable that is defined in your
+``CMakelists.txt`` file also be available in your source code. In this case, we
+would like to print the project version.
+
+One way to accomplish this is by using a configured header file. We create an
+input file with one or more variables to replace. These variables have special
+syntax which looks like ``@VAR@``.
+Then, we use the :command:`configure_file` command to copy the input file to a
+given output file and replace these variables with the current value of ``VAR``
+in the ``CMakelists.txt`` file.
+
+While we could edit the version directly in the source code, using this
+feature is preferred since it creates a single source of truth and avoids
+duplication.
+
+Goal
+----
+
+Define and report the project's version number.
+
+Helpful Resources
+-----------------
+
+* :variable:`<PROJECT-NAME>_VERSION_MAJOR`
+* :variable:`<PROJECT-NAME>_VERSION_MINOR`
+* :command:`configure_file`
+* :command:`target_include_directories`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+* ``tutorial.cxx``
+
+Getting Started
+---------------
+
+Continue to edit files from ``Step1``. Start on ``TODO 7`` and complete through
+``TODO 12``. In this exercise, we start by adding a project version number in
+``CMakeLists.txt``. In that same file, use :command:`configure_file` to copy a
+given input file to an output file and substitute some variable values in the
+input file content.
+
+Next, create an input header file ``TutorialConfig.h.in`` defining version
+numbers which will accept variables passed from :command:`configure_file`.
+
+Finally, update ``tutorial.cxx`` to print out its version number.
+
+Build and Run
+-------------
+
+Let's build our project again. As before, we already created a build directory
+and ran CMake so we can skip to the build step:
.. code-block:: console
cd Step1_build
cmake --build .
-Now we can try to use the newly built ``Tutorial`` with same commands as before:
+Verify that the version number is now reported when running the executable
+without any arguments.
-.. code-block:: console
+Solution
+--------
- Tutorial 4294967296
- Tutorial 10
- Tutorial
+In this exercise, we improve our executable by printing a version number.
+While we could do this exclusively in the source code, using ``CMakeLists.txt``
+lets us maintain a single source of data for the version number.
+
+First, we modify the ``CMakeLists.txt`` file to use the
+:command:`project` command to set both the project name and version number.
+When the :command:`project` command is called, CMake defines
+``Tutorial_VERSION_MAJOR`` and ``Tutorial_VERSION_MINOR`` behind the scenes.
+
+.. raw:: html
+
+ <details><summary>TODO 7: Click to show/hide answer</summary>
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: TODO 7: CMakeLists.txt
+ :name: CMakeLists.txt-project-VERSION
+ :language: cmake
+ :start-after: # set the project name and version
+ :end-before: # specify the C++ standard
+
+.. raw:: html
+
+ </details>
+
+Then we used :command:`configure_file` to copy the input file with the
+specified CMake variables replaced:
+
+.. raw:: html
+
+ <details><summary>TODO 8: Click to show/hide answer</summary>
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: TODO 8: CMakeLists.txt
+ :name: CMakeLists.txt-configure_file
+ :language: cmake
+ :start-after: # to the source code
+ :end-before: # TODO 8:
+
+.. raw:: html
+
+ </details>
+
+Since the configured file will be written into the project binary
+directory, we must add that directory to the list of paths to search for
+include files.
+
+**Note:** Throughout this tutorial, we will refer to the project build and
+the project binary directory interchangeably. These are the same and are not
+meant to refer to a `bin/` directory.
+
+We used :command:`target_include_directories` to specify
+where the executable target should look for include files.
+
+.. raw:: html
+
+ <details><summary>TODO 9: Click to show/hide answer</summary>
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: TODO 9: CMakeLists.txt
+ :name: CMakeLists.txt-target_include_directories
+ :language: cmake
+ :start-after: # so that we will find TutorialConfig.h
+
+.. raw:: html
+
+ </details>
+
+``TutorialConfig.h.in`` is the input header file to be configured.
+When :command:`configure_file` is called from our ``CMakeLists.txt``, the
+values for ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will
+be replaced with the corresponding version numbers from the project in
+``TutorialConfig.h``.
+
+.. raw:: html
+
+ <details><summary>TODO 10: Click to show/hide answer</summary>
+
+.. literalinclude:: Step2/TutorialConfig.h.in
+ :caption: TODO 10: TutorialConfig.h.in
+ :name: TutorialConfig.h.in
+ :language: c++
+ :end-before: // TODO 13:
+
+.. raw:: html
+
+ </details>
+
+Next, we need to modify ``tutorial.cxx`` to include the configured header file,
+``TutorialConfig.h``.
+
+.. raw:: html
+
+ <details><summary>TODO 11: Click to show/hide answer</summary>
+
+.. code-block:: c++
+ :caption: TODO 11: tutorial.cxx
+
+ #include "TutorialConfig.h"
+
+.. raw:: html
+
+ </details>
+
+Finally, we print out the executable name and version number by updating
+``tutorial.cxx`` as follows:
+
+.. raw:: html
+
+ <details><summary>TODO 12: Click to show/hide answer</summary>
+
+.. literalinclude:: Step2/tutorial.cxx
+ :caption: TODO 12 : tutorial.cxx
+ :name: tutorial.cxx-print-version
+ :language: c++
+ :start-after: {
+ :end-before: // convert input to double
+
+.. raw:: html
-Check that the version number is now reported when running the executable without
-any arguments.
+ </details>
diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst
index 3bd6d6464..eb14f4284 100644
--- a/Help/guide/tutorial/Adding Export Configuration.rst
+++ b/Help/guide/tutorial/Adding Export Configuration.rst
@@ -21,7 +21,7 @@ in ``MathFunctions/CMakeLists.txt`` to look like:
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT
:language: cmake
- :start-after: # install rules
+ :start-after: # install libs
Now that we have ``MathFunctions`` being exported, we also need to explicitly
install the generated ``MathFunctionsTargets.cmake`` file. This is done by
diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst
index 7fcc97fcc..6f9714e47 100644
--- a/Help/guide/tutorial/Adding Generator Expressions.rst
+++ b/Help/guide/tutorial/Adding Generator Expressions.rst
@@ -1,4 +1,4 @@
-Step 10: Adding Generator Expressions
+Step 4: Adding Generator Expressions
=====================================
:manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated
@@ -27,58 +27,280 @@ expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the
empty string, and ``<1:...>`` results in the content of ``...``. They can also
be nested.
+Exercise 1 - Setting the C++ Standard with Interface Libraries
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Before we use :manual:`generator expressions <cmake-generator-expressions(7)>`
+let's refactor our existing code to use an ``INTERFACE`` library. We will
+use that library in the next step to demonstrate a common use for
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+Goal
+----
+
+Add an ``INTERFACE`` library target to specify the required C++ standard.
+
+Helpful Resources
+-----------------
+
+* :command:`add_library`
+* :command:`target_compile_features`
+* :command:`target_link_libraries`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+* ``MathFunctions/CMakeLists.txt``
+
+Getting Started
+---------------
+
+In this exercise, we will refactor our code to use an ``INTERFACE`` library to
+specify the C++ standard.
+
+The starting source code is provided in the ``Step4`` directory. In this
+exercise, complete ``TODO 1`` through ``TODO 3``.
+
+Start by editing the top level ``CMakeLists.txt`` file. Construct an
+``INTERFACE`` library target called ``tutorial_compiler_flags`` and
+specify ``cxx_std_11`` as a target compiler feature.
+
+Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all
+targets have a :command:`target_link_libraries` call to
+``tutorial_compiler_flags``.
+
+Build and Run
+-------------
+
+Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>`
+executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project
+and then build it with your chosen build tool or by using ``cmake --build .``
+from the build directory.
+
+Here's a refresher of what that looks like from the command line:
+
+.. code-block:: console
+
+ mkdir Step4_build
+ cd Step4_build
+ cmake ../Step4
+ cmake --build .
+
+Next, use the newly built ``Tutorial`` and verify that it is working as
+expected.
+
+Solution
+--------
+
+Let's update our code from the previous step to use interface libraries
+to set our C++ requirements.
+
+To start, we need to remove the two :command:`set` calls on the variables
+:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`.
+The specific lines to remove are as follows:
+
+.. literalinclude:: Step4/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-CXX_STANDARD-variable-remove
+ :language: cmake
+ :start-after: # specify the C++ standard
+ :end-before: # TODO 5: Create helper variables
+
+Next, we need to create an interface library, ``tutorial_compiler_flags``. And
+then use :command:`target_compile_features` to add the compiler feature
+``cxx_std_11``.
+
+
+.. raw:: html
+
+ <details><summary>TODO 1: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: TODO 1: CMakeLists.txt
+ :name: CMakeLists.txt-cxx_std-feature
+ :language: cmake
+ :start-after: # specify the C++ standard
+ :end-before: # add compiler warning flags just
+
+.. raw:: html
+
+ </details>
+
+Finally, with our interface library set up, we need to link our
+executable ``Target`` and our ``MathFunctions`` library to our new
+``tutorial_compiler_flags`` library. Respectively, the code will look like
+this:
+
+.. raw:: html
+
+ <details><summary>TODO 2: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: TODO 2: CMakeLists.txt
+ :name: CMakeLists.txt-target_link_libraries-step4
+ :language: cmake
+ :start-after: add_executable(Tutorial tutorial.cxx)
+ :end-before: # add the binary tree to the search path for include file
+
+.. raw:: html
+
+ </details>
+
+and this:
+
+.. raw:: html
+
+ <details><summary>TODO 3: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
+ :caption: TODO 3: MathFunctions/CMakeLists.txt
+ :name: MathFunctions-CMakeLists.txt-target_link_libraries-step4
+ :language: cmake
+ :start-after: # link our compiler flags interface library
+ :end-before: # TODO 1
+
+.. raw:: html
+
+ </details>
+
+With this, all of our code still requires C++ 11 to build. Notice
+though that with this method, it gives us the ability to be specific about
+which targets get specific requirements. In addition, we create a single
+source of truth in our interface library.
+
+Exercise 2 - Adding Compiler Warning Flags with Generator Expressions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
A common usage of
:manual:`generator expressions <cmake-generator-expressions(7)>` is to
conditionally add compiler flags, such as those for language levels or
warnings. A nice pattern is to associate this information to an ``INTERFACE``
-target allowing this information to propagate. Let's start by constructing an
-``INTERFACE`` target and specifying the required C++ standard level of ``11``
-instead of using :variable:`CMAKE_CXX_STANDARD`.
+target allowing this information to propagate.
-So the following code:
+Goal
+----
-.. literalinclude:: Step10/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-CXX_STANDARD-variable-remove
+Add compiler warning flags when building but not for installed versions.
+
+Helpful Resources
+-----------------
+
+* :manual:`cmake-generator-expressions(7)`
+* :command:`cmake_minimum_required`
+* :command:`set`
+* :command:`target_compile_options`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+
+Getting Started
+---------------
+
+Start with the resulting files from Exercise 1. Complete ``TODO 4`` through
+``TODO 7``.
+
+First, in the top level ``CMakeLists.txt`` file, we need to set the
+:command:`cmake_minimum_required` to ``3.15``. In this exercise we are going
+to use a generator expression which was introduced in CMake 3.15.
+
+Next we add the desired compiler warning flags that we want for our project.
+As warning flags vary based on the compiler, we use the
+``COMPILE_LANG_AND_ID`` generator expression to control which flags to apply
+given a language and a set of compiler ids.
+
+Build and Run
+-------------
+
+Since we have our build directory already configured from Exercise 1, simply
+rebuild our code by calling the following:
+
+.. code-block:: console
+
+ cd Step4_build
+ cmake --build .
+
+Solution
+--------
+
+Update the :command:`cmake_minimum_required` to require at least CMake
+version ``3.15``:
+
+.. raw:: html
+
+ <details><summary>TODO 4: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: TODO 4: CMakeLists.txt
+ :name: MathFunctions-CMakeLists.txt-minimum-required-step4
:language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # control where the static and shared libraries are built so that on windows
+ :end-before: # set the project name and version
-Would be replaced with:
+.. raw:: html
-.. literalinclude:: Step11/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-cxx_std-feature
+ </details>
+
+Next we determine which compiler our system is currently using to build
+since warning flags vary based on the compiler we use. This is done with
+the ``COMPILE_LANG_AND_ID`` generator expression. We set the result in the
+variables ``gcc_like_cxx`` and ``msvc_cxx`` as follows:
+
+.. raw:: html
+
+ <details><summary>TODO 5: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: TODO 5: CMakeLists.txt
+ :name: CMakeLists.txt-compile_lang_and_id
:language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # add compiler warning flags just when building this project via
+ :start-after: # the BUILD_INTERFACE genex
+ :end-before: target_compile_options(tutorial_compiler_flags INTERFACE
-**Note**: This upcoming section will require a change to the
-:command:`cmake_minimum_required` usage in the code. The Generator Expression
-that is about to be used was introduced in `3.15`. Update the call to require
-that more recent version:
+.. raw:: html
+
+ </details>
+
+Next we add the desired compiler warning flags that we want for our project.
+Using our variables ``gcc_like_cxx`` and ``msvc_cxx``, we can use another
+generator expression to apply the respective flags only when the variables are
+true. We use :command:`target_compile_options` to apply these flags to our
+interface library.
+
+.. raw:: html
+
+ <details><summary>TODO 6: Click to show/hide answer</summary>
.. code-block:: cmake
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-version-update
+ :caption: TODO 6: CMakeLists.txt
+ :name: CMakeLists.txt-compile_flags
- cmake_minimum_required(VERSION 3.15)
+ target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>"
+ "$<${msvc_cxx}:-W3>"
+ )
-Next we add the desired compiler warning flags that we want for our project. As
-warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID``
-generator expression to control which flags to apply given a language and a set
-of compiler ids as seen below:
+.. raw:: html
-.. literalinclude:: Step11/CMakeLists.txt
- :caption: CMakeLists.txt
+ </details>
+
+Lastly, we only want these warning flags to be used during builds. Consumers
+of our installed project should not inherit our warning flags. To specify
+this, we wrap our flags in a generator expression using the ``BUILD_INTERFACE``
+condition. The resulting full code looks like the following:
+
+.. raw:: html
+
+ <details><summary>TODO 7: Click to show/hide answer</summary>
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: TODO 7: CMakeLists.txt
:name: CMakeLists.txt-target_compile_options-genex
:language: cmake
- :start-after: # the BUILD_INTERFACE genex
- :end-before: # control where the static and shared libraries are built so that on windows
+ :start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+ :end-before: # should we use our own math functions
-Looking at this we see that the warning flags are encapsulated inside a
-``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
-project will not inherit our warning flags.
+.. raw:: html
-**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have
-a :command:`target_link_libraries` call to ``tutorial_compiler_flags``.
+ </details>
diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
index c6e0fd0b3..45d597698 100644
--- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
+++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
@@ -1,4 +1,4 @@
-Step 8: Adding Support for a Testing Dashboard
+Step 6: Adding Support for a Testing Dashboard
==============================================
Adding support for submitting our test results to a dashboard is simple. We
@@ -9,21 +9,21 @@ we include the :module:`CTest` module in our top-level ``CMakeLists.txt``.
Replace:
-.. code-block:: cmake
+.. literalinclude:: Step6/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-enable_testing-remove
-
- # enable testing
- enable_testing()
+ :language: cmake
+ :start-after: # enable testing
+ :end-before: # does the application run
With:
-.. code-block:: cmake
+.. literalinclude:: Step7/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-include-CTest
-
- # enable dashboard scripting
- include(CTest)
+ :language: cmake
+ :start-after: # enable testing
+ :end-before: # does the application run
The :module:`CTest` module will automatically call ``enable_testing()``, so we
can remove it from our CMake files.
@@ -46,7 +46,7 @@ downloaded from the ``Settings`` page of the project on the CDash
instance that will host and display the test results. Once downloaded from
CDash, the file should not be modified locally.
-.. literalinclude:: Step9/CTestConfig.cmake
+.. literalinclude:: Step7/CTestConfig.cmake
:caption: CTestConfig.cmake
:name: CTestConfig.cmake
:language: cmake
diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst
index 8db0cb8f3..ba91df47e 100644
--- a/Help/guide/tutorial/Adding System Introspection.rst
+++ b/Help/guide/tutorial/Adding System Introspection.rst
@@ -1,4 +1,4 @@
-Step 5: Adding System Introspection
+Step 7: Adding System Introspection
===================================
Let us consider adding some code to our project that depends on features the
@@ -15,7 +15,7 @@ these functions using the :module:`CheckCXXSourceCompiles` module in
Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``,
after the call to :command:`target_include_directories`:
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
:language: cmake
@@ -25,19 +25,19 @@ after the call to :command:`target_include_directories`:
If available, use :command:`target_compile_definitions` to specify
``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake
:start-after: # add compile definitions
- :end-before: # install rules
+ :end-before: # install libs
If ``log`` and ``exp`` are available on the system, then we will use them to
compute the square root in the ``mysqrt`` function. Add the following code to
the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the
``#endif`` before returning the result!):
-.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step8/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-ifdef
:language: c++
@@ -46,7 +46,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the
We will also need to modify ``mysqrt.cxx`` to include ``cmath``.
-.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step8/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst
index a8e914eda..4aef05058 100644
--- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst
+++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst
@@ -1,52 +1,147 @@
Step 3: Adding Usage Requirements for a Library
===============================================
-Usage requirements allow for far better control over a library or executable's
-link and include line while also giving more control over the transitive
-property of targets inside CMake. The primary commands that leverage usage
-requirements are:
-
- - :command:`target_compile_definitions`
- - :command:`target_compile_options`
- - :command:`target_include_directories`
- - :command:`target_link_libraries`
-
-Let's refactor our code from :guide:`tutorial/Adding a Library` to use the
-modern CMake approach of usage requirements. We first state that anybody
-linking to ``MathFunctions`` needs to include the current source directory,
-while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE``
-usage requirement.
-
-Remember ``INTERFACE`` means things that consumers require but the producer
-doesn't. Add the following lines to the end of
-``MathFunctions/CMakeLists.txt``:
+Exercise 1 - Adding Usage Requirements for a Library
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+:ref:`Usage requirements <Target Usage Requirements>` of a target parameters
+allow for far better control over a library or executable's link and include
+line while also giving more control over the transitive property of targets
+inside CMake. The primary commands that
+leverage usage requirements are:
+
+* :command:`target_compile_definitions`
+* :command:`target_compile_options`
+* :command:`target_include_directories`
+* :command:`target_link_directories`
+* :command:`target_link_options`
+* :command:`target_precompile_headers`
+* :command:`target_sources`
+
+
+Goal
+----
+
+Add usage requirements for a library.
+
+Helpful Materials
+-----------------
+
+* :variable:`CMAKE_CURRENT_SOURCE_DIR`
+
+Files to Edit
+-------------
+
+* ``MathFunctions/CMakeLists.txt``
+* ``CMakeLists.txt``
+
+Getting Started
+---------------
+
+In this exercise, we will refactor our code from
+:guide:`tutorial/Adding a Library` to use the modern CMake approach. We will
+let our library define its own usage requirements so they are passed
+transitively to other targets as necessary. In this case, ``MathFunctions``
+will specify any needed include directories itself. Then, the consuming target
+``Tutorial`` simply needs to link to ``MathFunctions`` and not worry about
+any additional include directories.
+
+The starting source code is provided in the ``Step3`` directory. In this
+exercise, complete ``TODO 1`` through ``TODO 3``.
+
+First, add a call to :command:`target_include_directories` in
+``MathFunctions/CMakeLists``. Remember that
+:variable:`CMAKE_CURRENT_SOURCE_DIR` is the path to the source directory
+currently being processed.
+
+Then, update (and simplify!) the call to
+:command:`target_include_directories` in the top-level ``CMakeLists.txt``.
+
+Build and Run
+-------------
+
+Make a new directory called ``Step3_build``, run the :manual:`cmake
+<cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to
+configure the project and then build it with your chosen build tool or by
+using :option:`cmake --build . <cmake --build>` from the build directory.
+Here's a refresher of what that looks like from the command line:
+
+.. code-block:: console
+
+ mkdir Step3_build
+ cd Step3_build
+ cmake ../Step3
+ cmake --build .
+
+Next, use the newly built ``Tutorial`` and verify that it is working as
+expected.
+
+Solution
+--------
+
+Let's update the code from the previous step to use the modern CMake
+approach of usage requirements.
+
+We want to state that anybody linking to ``MathFunctions`` needs to include
+the current source directory, while ``MathFunctions`` itself doesn't. This
+can be expressed with an ``INTERFACE`` usage requirement. Remember
+``INTERFACE`` means things that consumers require but the producer doesn't.
+
+At the end of ``MathFunctions/CMakeLists.txt``, use
+:command:`target_include_directories` with the ``INTERFACE`` keyword, as
+follows:
+
+.. raw:: html
+
+ <details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
- :caption: MathFunctions/CMakeLists.txt
+ :caption: TODO 1: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
:language: cmake
:start-after: # to find MathFunctions.h
+ :end-before: # TODO 3: Link to
+
+.. raw:: html
+
+ </details>
-Now that we've specified usage requirements for ``MathFunctions`` we can safely
-remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
+Now that we've specified usage requirements for ``MathFunctions`` we can
+safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
``CMakeLists.txt``, here:
+.. raw:: html
+
+ <details><summary>TODO 2: Click to show/hide answer</summary>
+
.. literalinclude:: Step4/CMakeLists.txt
- :caption: CMakeLists.txt
+ :caption: TODO 2: CMakeLists.txt
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
:language: cmake
:start-after: # add the MathFunctions library
:end-before: # add the executable
+.. raw:: html
+
+ </details>
+
And here:
+.. raw:: html
+
+ <details><summary>TODO 3: Click to show/hide answer</summary>
+
.. literalinclude:: Step4/CMakeLists.txt
- :caption: CMakeLists.txt
+ :caption: TODO 3: CMakeLists.txt
:name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
:language: cmake
:start-after: # so that we will find TutorialConfig.h
-Once this is done, run the :manual:`cmake <cmake(1)>` executable or the
-:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
-with your chosen build tool or by using ``cmake --build .`` from the build
-directory.
+.. raw:: html
+
+ </details>
+
+Notice that with this technique, the only thing our executable target does to
+use our library is call :command:`target_link_libraries` with the name
+of the library target. In larger projects, the classic method of specifying
+library dependencies manually becomes very complicated very quickly.
diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
index 70c669562..b1f984076 100644
--- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
+++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
@@ -1,4 +1,4 @@
-Step 6: Adding a Custom Command and Generated File
+Step 8: Adding a Custom Command and Generated File
==================================================
Suppose, for the purpose of this tutorial, we decide that we never want to use
@@ -26,7 +26,7 @@ accomplish this.
First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for
``MakeTable`` is added as any other executable would be added.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_executable-MakeTable
:language: cmake
@@ -36,7 +36,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for
Then we add a custom command that specifies how to produce ``Table.h``
by running MakeTable.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h
:language: cmake
@@ -47,7 +47,7 @@ Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated
file ``Table.h``. This is done by adding the generated ``Table.h`` to the list
of sources for the library MathFunctions.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_library-Table.h
:language: cmake
@@ -57,17 +57,17 @@ of sources for the library MathFunctions.
We also have to add the current binary directory to the list of include
directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h
:language: cmake
:start-after: # state that we depend on our bin
- :end-before: # install rules
+ :end-before: # install libs
Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table:
-.. literalinclude:: Step7/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step9/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx
:language: c++
diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst
index 71755be35..a56c327ee 100644
--- a/Help/guide/tutorial/Adding a Library.rst
+++ b/Help/guide/tutorial/Adding a Library.rst
@@ -1,136 +1,459 @@
Step 2: Adding a Library
========================
-Now we will add a library to our project. This library will contain our own
+At this point, we have seen how to create a basic project using CMake. In this
+step, we will learn how to create and use a library in our project. We will
+also see how to make the use of our library optional.
+
+Exercise 1 - Creating a Library
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To add a library in CMake, use the :command:`add_library` command and specify
+which source files should make up the library.
+
+Rather than placing all of the source files in one directory, we can organize
+our project with one or more subdirectories. In this case, we will create a
+subdirectory specifically for our library. Here, we can add a new
+``CMakeLists.txt`` file and one or more source files. In the top level
+``CMakeLists.txt`` file, we will use the :command:`add_subdirectory` command
+to add the subdirectory to the build.
+
+Once the library is created, it is connected to our executable target with
+:command:`target_include_directories` and :command:`target_link_libraries`.
+
+Goal
+----
+
+Add and use a library.
+
+Helpful Resources
+-----------------
+
+* :command:`add_library`
+* :command:`add_subdirectory`
+* :command:`target_include_directories`
+* :command:`target_link_libraries`
+* :variable:`PROJECT_SOURCE_DIR`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+* ``tutorial.cxx``
+* ``MathFunctions/CMakeLists.txt``
+
+Getting Started
+---------------
+
+In this exercise, we will add a library to our project that contains our own
implementation for computing the square root of a number. The executable can
then use this library instead of the standard square root function provided by
the compiler.
-For this tutorial we will put the library into a subdirectory
-called ``MathFunctions``. This directory already contains a header file,
-``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one
-function called ``mysqrt`` that provides similar functionality to the
-compiler's ``sqrt`` function.
+For this tutorial we will put the library into a subdirectory called
+``MathFunctions``. This directory already contains a header file,
+``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to
+modify either of these files. The source file has one function called
+``mysqrt`` that provides similar functionality to the compiler's ``sqrt``
+function.
+
+From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and
+complete through ``TODO 6``.
+
+First, fill in the one line ``CMakeLists.txt`` in the ``MathFunctions``
+subdirectory.
+
+Next, edit the top level ``CMakeLists.txt``.
+
+Finally, use the newly created ``MathFunctions`` library in ``tutorial.cxx``
+
+Build and Run
+-------------
+
+Run the :manual:`cmake <cmake(1)>` executable or the
+:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
+with your chosen build tool.
+
+Below is a refresher of what that looks like from the command line:
+
+.. code-block:: console
+
+ mkdir Step2_build
+ cd Step2_build
+ cmake ../Step2
+ cmake --build .
+
+Try to use the newly built ``Tutorial`` and ensure that it is still
+producing accurate square root values.
+
+Solution
+--------
+
+In the ``CMakeLists.txt`` file in the ``MathFunctions`` directory, we create
+a library target called ``MathFunctions`` with :command:`add_library`. The
+source file for the library is passed as an argument to
+:command:`add_library`. This looks like the following line:
-Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
-directory:
+.. raw:: html
+
+ <details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
- :caption: MathFunctions/CMakeLists.txt
- :name: MathFunctions/CMakeLists.txt
+ :caption: TODO 1: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-add_library
:language: cmake
+ :end-before: # TODO 1
+
+.. raw:: html
+
+ </details>
To make use of the new library we will add an :command:`add_subdirectory`
call in the top-level ``CMakeLists.txt`` file so that the library will get
-built. We add the new library to the executable, and add ``MathFunctions`` as
-an include directory so that the ``MathFunctions.h`` header file can be found.
-The last few lines of the top-level ``CMakeLists.txt`` file should now look
-like:
+built.
+
+.. raw:: html
+
+ <details><summary>TODO 2: Click to show/hide answer</summary>
+
+.. code-block:: cmake
+ :caption: TODO 2: CMakeLists.txt
+ :name: CMakeLists.txt-add_subdirectory
+
+ add_subdirectory(MathFunctions)
+
+.. raw:: html
+
+ </details>
+
+Next, the new library target is linked to the executable target using
+:command:`target_link_libraries`.
+
+.. raw:: html
+
+ <details><summary>TODO 3: Click to show/hide answer</summary>
+
+.. code-block:: cmake
+ :caption: TODO 3: CMakeLists.txt
+ :name: CMakeLists.txt-target_link_libraries
+
+ target_link_libraries(Tutorial PUBLIC MathFunctions)
+
+.. raw:: html
+
+ </details>
+
+Finally we need to specify the library's header file location. Modify
+:command:`target_include_directories` to add the ``MathFunctions`` subdirectory
+as an include directory so that the ``MathFunctions.h`` header file can be
+found.
+
+.. raw:: html
+
+ <details><summary>TODO 4: Click to show/hide answer</summary>
.. code-block:: cmake
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-add_subdirectory
+ :caption: TODO 4: CMakeLists.txt
+ :name: CMakeLists.txt-target_include_directories-step2
+
+ target_include_directories(Tutorial PUBLIC
+ "${PROJECT_BINARY_DIR}"
+ "${PROJECT_SOURCE_DIR}/MathFunctions"
+ )
+
+.. raw:: html
+
+ </details>
+
+Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``:
+
+.. raw:: html
+
+ <details><summary>TODO 5: Click to show/hide answer</summary>
- # add the MathFunctions library
- add_subdirectory(MathFunctions)
+.. code-block:: c++
+ :caption: TODO 5 : tutorial.cxx
+ :name: tutorial.cxx-include_MathFunctions.h
- # add the executable
- add_executable(Tutorial tutorial.cxx)
+ #include "MathFunctions.h"
- target_link_libraries(Tutorial PUBLIC MathFunctions)
+.. raw:: html
- # add the binary tree to the search path for include files
- # so that we will find TutorialConfig.h
- target_include_directories(Tutorial PUBLIC
- "${PROJECT_BINARY_DIR}"
- "${PROJECT_SOURCE_DIR}/MathFunctions"
- )
+ </details>
-Now let us make the ``MathFunctions`` library optional. While for the tutorial
+Lastly, replace ``sqrt`` with our library function ``mysqrt``.
+
+.. raw:: html
+
+ <details><summary>TODO 6: Click to show/hide answer</summary>
+
+.. code-block:: c++
+ :caption: TODO 6 : tutorial.cxx
+ :name: tutorial.cxx-call_mysqrt
+
+ const double outputValue = mysqrt(inputValue);
+
+.. raw:: html
+
+ </details>
+
+Exercise 2 - Making Our Library Optional
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Now let us make the MathFunctions library optional. While for the tutorial
there really isn't any need to do so, for larger projects this is a common
-occurrence. The first step is to add an option to the top-level
-``CMakeLists.txt`` file.
+occurrence.
+
+CMake can do this using the :command:`option` command. This gives users a
+variable which they can change when configuring their cmake build. This
+setting will be stored in the cache so that the user does not need to set
+the value each time they run CMake on a build directory.
+
+Goal
+----
+
+Add the option to build without ``MathFunctions``.
+
+
+Helpful Resources
+-----------------
+
+* :command:`if`
+* :command:`list`
+* :command:`option`
+* :command:`cmakedefine <configure_file>`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+* ``tutorial.cxx``
+* ``TutorialConfig.h.in``
+
+Getting Started
+---------------
+
+Start with the resulting files from Exercise 1. Complete ``TODO 7`` through
+``TODO 13``.
+
+First create a variable ``USE_MYMATH`` using the :command:`option` command
+in the top-level ``CMakeLists.txt`` file. In that same file, use that option
+to determine whether to build and use the ``MathFunctions`` library.
+
+Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use
+``USE_MYMATH``.
+
+Build and Run
+-------------
+
+Since we have our build directory already configured from Exercise 1, we can
+rebuild by simply calling the following:
+
+.. code-block:: console
+
+ cd ../Step2_build
+ cmake --build .
+
+Next, run the ``Tutorial`` executable on a few numbers to verify that it's
+still correct.
+
+Now let's update the value of ``USE_MYMATH`` to ``OFF``. The easiest way is to
+use the :manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>`
+if you're in the terminal. Or, alternatively, if you want to change the
+option from the command-line, try:
+
+.. code-block:: console
+
+ cmake ../Step2 -DUSE_MYMATH=OFF
+
+Now, rebuild the code with the following:
+
+.. code-block:: console
+
+ cmake --build .
+
+Then, run the executable again to ensure that it still works with
+``USE_MYMATH`` set to ``OFF``. Which function gives better results, ``sqrt``
+or ``mysqrt``?
+
+Solution
+--------
+
+The first step is to add an option to the top-level ``CMakeLists.txt`` file.
+This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
+:manual:`ccmake <ccmake(1)>` with a default value of ``ON`` that can be
+changed by the user.
+
+.. raw:: html
+
+ <details><summary>TODO 7: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
- :caption: CMakeLists.txt
+ :caption: TODO 7: CMakeLists.txt
:name: CMakeLists.txt-option
:language: cmake
:start-after: # should we use our own math functions
- :end-before: # add the MathFunctions library
+ :end-before: # configure a header file to pass some of the CMake settings
-This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
-:manual:`ccmake <ccmake(1)>`
-with a default value of ``ON`` that can be changed by the user. This setting
-will be stored in the cache so that the user does not need to set the value
-each time they run CMake on a build directory.
-
-The next change is to make building and linking the ``MathFunctions`` library
-conditional. To do this, we will create an ``if`` statement which checks the
-value of the option. Inside the ``if`` block, put the
-:command:`add_subdirectory` command from above with some additional list
-commands to store information needed to link to the library and add the
-subdirectory as an include directory in the ``Tutorial`` target.
-The end of the top-level ``CMakeLists.txt`` file will now look like the
-following:
+.. raw:: html
+
+ </details>
+
+Next, make building and linking the ``MathFunctions`` library
+conditional.
+
+Start by creating a :command:`list` of the optional library targets for our
+project. At the moment, it is just ``MathFunctions``. Let's name our list
+``EXTRA_LIBS``.
+
+Similarly, we need to make a :command:`list` for the optional includes which
+we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of
+the header file needed for our library.
+
+Next, create an :command:`if` statement which checks the value of
+``USE_MYMATH``. Inside the :command:`if` block, put the
+:command:`add_subdirectory` command from Exercise 1 with the additional
+:command:`list` commands.
+
+When ``USE_MYMATH`` is ``ON``, the lists will be generated and will be added to
+our project. When ``USE_MYMATH`` is ``OFF``, the lists stay empty. With this
+strategy, we allow users to toggle ``USE_MYMATH`` to manipulate what library is
+used in the build.
+
+The top-level CMakeLists.txt file will now look like the following:
+
+.. raw:: html
+
+ <details><summary>TODO 8: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
+ :caption: TODO 8: CMakeLists.txt
+ :name: CMakeLists.txt-USE_MYMATH
:language: cmake
:start-after: # add the MathFunctions library
+ :end-before: # add the executable
+
+.. raw:: html
+
+ </details>
-Note the use of the variable ``EXTRA_LIBS`` to collect up any optional
-libraries to later be linked into the executable. The variable
-``EXTRA_INCLUDES`` is used similarly for optional header files. This is a
-classic approach when dealing with many optional components, we will cover
-the modern approach in the next step.
+Now that we have these two lists, we need to update
+:command:`target_link_libraries` and :command:`target_include_directories` to
+use them. Changing them is fairly straightforward.
+
+For :command:`target_link_libraries`, we replace the written out
+library names with ``EXTRA_LIBS``. This looks like the following:
+
+.. raw:: html
+
+ <details><summary>TODO 9: Click to show/hide answer</summary>
+
+.. literalinclude:: Step3/CMakeLists.txt
+ :caption: TODO 9: CMakeLists.txt
+ :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
+ :language: cmake
+ :start-after: add_executable(Tutorial tutorial.cxx)
+ :end-before: # TODO 3
+
+.. raw:: html
+
+ </details>
+
+Then, we do the same thing with :command:`target_include_directories` and
+``EXTRA_INCLUDES``.
+
+.. raw:: html
+
+ <details><summary>TODO 10: Click to show/hide answer</summary>
+
+.. literalinclude:: Step3/CMakeLists.txt
+ :caption: TODO 10 : CMakeLists.txt
+ :name: CMakeLists.txt-target_link_libraries-EXTRA_INCLUDES
+ :language: cmake
+ :start-after: # so that we will find TutorialConfig.h
+
+.. raw:: html
+
+ </details>
+
+Note that this is a classic approach when dealing with many components. We
+will cover the modern approach in the Step 3 of the tutorial.
The corresponding changes to the source code are fairly straightforward.
-First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
-need it:
+First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if
+``USE_MYMATH`` is defined.
+
+.. raw:: html
+
+ <details><summary>TODO 11: Click to show/hide answer</summary>
.. literalinclude:: Step3/tutorial.cxx
- :caption: tutorial.cxx
+ :caption: TODO 11 : tutorial.cxx
:name: tutorial.cxx-ifdef-include
:language: c++
:start-after: // should we include the MathFunctions header
:end-before: int main
-Then, in the same file, make ``USE_MYMATH`` control which square root
+.. raw:: html
+
+ </details>
+
+Then, in the same file, we make ``USE_MYMATH`` control which square root
function is used:
+.. raw:: html
+
+ <details><summary>TODO 12: Click to show/hide answer</summary>
+
.. literalinclude:: Step3/tutorial.cxx
- :caption: tutorial.cxx
+ :caption: TODO 12 : tutorial.cxx
:name: tutorial.cxx-ifdef-const
:language: c++
:start-after: // which square root function should we use?
:end-before: std::cout << "The square root of
+.. raw:: html
+
+ </details>
+
Since the source code now requires ``USE_MYMATH`` we can add it to
``TutorialConfig.h.in`` with the following line:
+.. raw:: html
+
+ <details><summary>TODO 13: Click to show/hide answer</summary>
+
.. literalinclude:: Step3/TutorialConfig.h.in
- :caption: TutorialConfig.h.in
+ :caption: TODO 13 : TutorialConfig.h.in
:name: TutorialConfig.h.in-cmakedefine
:language: c++
:lines: 4
-**Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
+.. raw:: html
+
+ </details>
+
+With these changes, our library is now completely optional to whoever is
+building and using it.
+
+Bonus Question
+--------------
+
+Why is it important that we configure ``TutorialConfig.h.in``
after the option for ``USE_MYMATH``? What would happen if we inverted the two?
-Run the :manual:`cmake <cmake(1)>` executable or the
-:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
-with your chosen build tool. Then run the built Tutorial executable.
+Answer
+------
-Now let's update the value of ``USE_MYMATH``. The easiest way is to use the
-:manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` if you're
-in the terminal. Or, alternatively, if you want to change the option from the
-command-line, try:
+.. raw:: html
-.. code-block:: console
+ <details><summary>Click to show/hide answer</summary>
- cmake ../Step2 -DUSE_MYMATH=OFF
+We configure after because ``TutorialConfig.h.in`` uses the value of
+``USE_MYMATH``. If we configure the file before
+calling :command:`option`, we won't be using the expected value of
+``USE_MYMATH``.
-Rebuild and run the tutorial again.
+.. raw:: html
-Which function gives better results, ``sqrt`` or ``mysqrt``?
+ </details>
diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt
index 41baf6484..3cdaaae45 100644
--- a/Help/guide/tutorial/Complete/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/CMakeLists.txt
@@ -41,7 +41,7 @@ add_subdirectory(MathFunctions)
add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
-target_link_libraries(Tutorial PUBLIC MathFunctions)
+target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -84,6 +84,7 @@ do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Help/guide/tutorial/Complete/License.txt b/Help/guide/tutorial/Complete/License.txt
index c62d00b9e..85760e591 100644
--- a/Help/guide/tutorial/Complete/License.txt
+++ b/Help/guide/tutorial/Complete/License.txt
@@ -1,2 +1,2 @@
This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
+CMake/Tutorial/Step9...
diff --git a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
index 40b9fd21a..d256db20a 100644
--- a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
@@ -56,7 +56,7 @@ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
-# install rules
+# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
@@ -64,4 +64,5 @@ endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst
index 394c9865f..fa13040ae 100644
--- a/Help/guide/tutorial/Installing and Testing.rst
+++ b/Help/guide/tutorial/Installing and Testing.rst
@@ -1,95 +1,311 @@
-Step 4: Installing and Testing
+Step 5: Installing and Testing
==============================
-Now we can start adding install rules and testing support to our project.
+.. _`Tutorial Testing Support`:
+
+Exercise 1 - Install Rules
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Often, it is not enough to only build an executable, it should also be
+installable. With CMake, we can specify install rules using the
+:command:`install` command. Supporting local installations for your builds in
+CMake is often as simple as specifying an install location and the targets and
+files to be installed.
+
+Goal
+----
+
+Install the ``Tutorial`` executable and the ``MathFunctions`` library.
+
+Helpful Materials
+-----------------
+
+* :command:`install`
-Install Rules
+Files to Edit
-------------
-The install rules are fairly simple: for ``MathFunctions`` we want to install
-the library and header file and for the application we want to install the
-executable and configured header.
+* ``MathFunctions/CMakeLists.txt``
+* ``CMakeLists.txt``
-So to the end of ``MathFunctions/CMakeLists.txt`` we add:
+Getting Started
+---------------
-.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
- :caption: MathFunctions/CMakeLists.txt
- :name: MathFunctions/CMakeLists.txt-install-TARGETS
- :language: cmake
- :start-after: # install rules
+The starting code is provided in the ``Step5`` directory. In this
+exercise, complete ``TODO 1`` through ``TODO 4``.
-And to the end of the top-level ``CMakeLists.txt`` we add:
+First, update ``MathFunctions/CMakeLists.txt`` to install the
+``MathFunctions`` and ``tutorial_compiler_flags`` libraries to the ``lib``
+directory. In that same file, specify the install rules needed to install
+``MathFunctions.h`` to the ``include`` directory.
-.. literalinclude:: Step5/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-install-TARGETS
- :language: cmake
- :start-after: # add the install targets
- :end-before: # enable testing
+Then, update the top level ``CMakeLists.txt`` to install
+the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files
+should be installed to the ``include`` directory. Remember that
+``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`.
-That is all that is needed to create a basic local install of the tutorial.
+Build and Run
+-------------
-Now run the :manual:`cmake <cmake(1)>` executable or the
+Make a new directory called ``Step5_build``. Run the
+:manual:`cmake <cmake(1)>` executable or the
:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
with your chosen build tool.
-Then run the install step by using the ``install`` option of the
-:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of
-CMake must use ``make install``) from the command line. For
-multi-configuration tools, don't forget to use the ``--config`` argument to
-specify the configuration. If using an IDE, simply build the ``INSTALL``
-target. This step will install the appropriate header files, libraries, and
-executables. For example:
+Then, run the install step by using the :option:`--install <cmake --install>`
+option of the :manual:`cmake <cmake(1)>` command (introduced in 3.15, older
+versions of CMake must use ``make install``) from the command line. This step
+will install the appropriate header files, libraries, and executables.
+For example:
.. code-block:: console
cmake --install .
+For multi-configuration tools, don't forget to use the
+:option:`--config <cmake--build --config>` argument to specify the configuration.
+
+.. code-block:: console
+
+ cmake --install . --config Release
+
+If using an IDE, simply build the ``INSTALL`` target. You can build the same
+install target from the command line like the following:
+
+.. code-block:: console
+
+ cmake --build . --target install --config Debug
+
The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the
-root of where the files will be installed. If using the ``cmake --install``
-command, the installation prefix can be overridden via the ``--prefix``
-argument. For example:
+root of where the files will be installed. If using the :option:`cmake --install`
+command, the installation prefix can be overridden via the
+:option:`--prefix <cmake--install --prefix>` argument. For example:
.. code-block:: console
cmake --install . --prefix "/home/myuser/installdir"
-Navigate to the install directory and verify that the installed Tutorial runs.
+Navigate to the install directory and verify that the installed ``Tutorial``
+runs.
-.. _`Tutorial Testing Support`:
+Solution
+--------
-Testing Support
----------------
+The install rules for our project are fairly simple:
-Next let's test our application. At the end of the top-level ``CMakeLists.txt``
-file we can enable testing and then add a number of basic tests to verify that
-the application is working correctly.
+* For ``MathFunctions``, we want to install the libraries and header file to
+ the ``lib`` and ``include`` directories respectively.
-.. literalinclude:: Step5/CMakeLists.txt
+* For the ``Tutorial`` executable, we want to install the executable and
+ configured header file to the ``bin`` and ``include`` directories
+ respectively.
+
+So to the end of ``MathFunctions/CMakeLists.txt`` we add:
+
+.. raw:: html
+
+ <details><summary>TODO 1: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+ :caption: TODO 1: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-install-TARGETS
+ :language: cmake
+ :start-after: # install libs
+ :end-before: # install include headers
+
+.. raw:: html
+
+ </details>
+
+and
+
+.. raw:: html
+
+ <details><summary>TODO 2: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+ :caption: TODO 2: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-install-headers
+ :language: cmake
+ :start-after: # install include headers
+
+.. raw:: html
+
+ </details>
+
+The install rules for the ``Tutorial`` executable and configured header file
+are similar. To the end of the top-level ``CMakeLists.txt`` we add:
+
+.. raw:: html
+
+ <details><summary>TODO 3,4: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/CMakeLists.txt
:caption: CMakeLists.txt
- :name: CMakeLists.txt-enable_testing
+ :name: TODO 3,4: CMakeLists.txt-install-TARGETS
:language: cmake
- :start-after: # enable testing
+ :start-after: # add the install targets
+ :end-before: # enable testing
+
+.. raw:: html
+
+ </details>
-The first test simply verifies that the application runs, does not segfault or
-otherwise crash, and has a zero return value. This is the basic form of a
-CTest test.
+That is all that is needed to create a basic local
+install of the tutorial.
-The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test
-property to verify that the output of the test contains certain strings. In
-this case, verifying that the usage message is printed when an incorrect number
-of arguments are provided.
+Exercise 2 - Testing Support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Lastly, we have a function called ``do_test`` that runs the application and
-verifies that the computed square root is correct for given input. For each
-invocation of ``do_test``, another test is added to the project with a name,
-input, and expected results based on the passed arguments.
+CTest offers a way to easily manage tests for your project. Tests can be
+added through the :command:`add_test` command. Although it is not
+explicitly covered in this tutorial, there is a lot of compatibility
+between CTest and other testing frameworks such as :module:`GoogleTest`.
-Rebuild the application and then cd to the binary directory and run the
-:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
+Goal
+----
+
+Create unit tests for our executable using CTest.
+
+Helpful Materials
+-----------------
+
+* :command:`enable_testing`
+* :command:`add_test`
+* :command:`function`
+* :command:`set_tests_properties`
+* :manual:`ctest <ctest(1)>`
+
+Files to Edit
+-------------
+
+* ``CMakeLists.txt``
+
+Getting Started
+---------------
+
+The starting source code is provided in the ``Step5`` directory. In this
+exercise, complete ``TODO 5`` through ``TODO 9``.
+
+First, we need to enable testing. Next, begin adding tests to our project
+using :command:`add_test`. We will work through adding 3 simple tests and
+then you can add additional testing as you see fit.
+
+Build and Run
+-------------
+
+Navigate to the build directory and rebuild the application. Then, run the
+``ctest`` executable: :option:`ctest -N` and :option:`ctest -VV`. For
multi-config generators (e.g. Visual Studio), the configuration type must be
-specified with the ``-C <mode>`` flag. For example, to run tests in Debug
-mode use ``ctest -C Debug -VV`` from the binary directory
+specified with the :option:`-C \<mode\> <ctest -C>` flag. For example, to run tests in Debug
+mode use ``ctest -C Debug -VV`` from the build directory
(not the Debug subdirectory!). Release mode would be executed from the same
-location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
+location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
target from the IDE.
+
+Solution
+--------
+
+Let's test our application. At the end of the top-level ``CMakeLists.txt``
+file we first need to enable testing with the
+:command:`enable_testing` command.
+
+.. raw:: html
+
+ <details><summary>TODO 5: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/CMakeLists.txt
+ :caption: TODO 5: CMakeLists.txt
+ :name: CMakeLists.txt-enable_testing
+ :language: cmake
+ :start-after: # enable testing
+ :end-before: # does the application run
+
+.. raw:: html
+
+ </details>
+
+With testing enabled, we will add a number of basic tests to verify
+that the application is working correctly. First, we create a test using
+:command:`add_test` which runs the ``Tutorial`` executable with the
+parameter 25 passed in. For this test, we are not going to check the
+executable's computed answer. This test will verify that
+application runs, does not segfault or otherwise crash, and has a zero
+return value. This is the basic form of a CTest test.
+
+.. raw:: html
+
+ <details><summary>TODO 6: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/CMakeLists.txt
+ :caption: TODO 6: CMakeLists.txt
+ :name: CMakeLists.txt-test-runs
+ :language: cmake
+ :start-after: # does the application run
+ :end-before: # does the usage message work
+
+.. raw:: html
+
+ </details>
+
+Next, let's use the :prop_test:`PASS_REGULAR_EXPRESSION` test property to
+verify that the output of the test contains certain strings. In this case,
+verifying that the usage message is printed when an incorrect number of
+arguments are provided.
+
+.. raw:: html
+
+ <details><summary>TODO 7: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/CMakeLists.txt
+ :caption: TODO 7: CMakeLists.txt
+ :name: CMakeLists.txt-test-usage
+ :language: cmake
+ :start-after: # does the usage message work?
+ :end-before: # define a function to simplify adding tests
+
+.. raw:: html
+
+ </details>
+
+The next test we will add verifies the computed value is truly the
+square root.
+
+.. raw:: html
+
+ <details><summary>TODO 8: Click to show/hide answer</summary>
+
+.. code-block:: cmake
+ :caption: TODO 8: CMakeLists.txt
+ :name: CMakeLists.txt-test-standard
+
+ add_test(NAME StandardUse COMMAND Tutorial 4)
+ set_tests_properties(StandardUse
+ PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2"
+ )
+
+.. raw:: html
+
+ </details>
+
+This one test is not enough to give us confidence that it will
+work for all values passed in. We should add more tests to verify this.
+To easily add more tests, we make a function called ``do_test`` that runs the
+application and verifies that the computed square root is correct for
+given input. For each invocation of ``do_test``, another test is added to
+the project with a name, input, and expected results based on the passed
+arguments.
+
+.. raw:: html
+
+ <details><summary>TODO 9: Click to show/hide answer</summary>
+
+.. literalinclude:: Step6/CMakeLists.txt
+ :caption: TODO 9: CMakeLists.txt
+ :name: CMakeLists.txt-generalized-tests
+ :language: cmake
+ :start-after: # define a function to simplify adding tests
+
+.. raw:: html
+
+ </details>
diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst
index 91b46a778..8c660a311 100644
--- a/Help/guide/tutorial/Packaging Debug and Release.rst
+++ b/Help/guide/tutorial/Packaging Debug and Release.rst
@@ -10,8 +10,8 @@ possible, however, to setup CPack to bundle multiple build directories and
construct a package that contains multiple configurations of the same project.
First, we want to ensure that the debug and release builds use different names
-for the executables and libraries that will be installed. Let's use `d` as the
-postfix for the debug executable and libraries.
+for the libraries that will be installed. Let's use `d` as the
+postfix for the debug libraries.
Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level
``CMakeLists.txt`` file:
@@ -41,10 +41,10 @@ Let's also add version numbering to the ``MathFunctions`` library. In
:name: MathFunctions/CMakeLists.txt-VERSION-properties
:language: cmake
:start-after: # setup the version numbering
- :end-before: # install rules
+ :end-before: # install libs
From the ``Step12`` directory, create ``debug`` and ``release``
-subbdirectories. The layout will look like:
+subdirectories. The layout will look like:
.. code-block:: none
diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst
index 0ee5db2ac..11a1952c8 100644
--- a/Help/guide/tutorial/Packaging an Installer.rst
+++ b/Help/guide/tutorial/Packaging an Installer.rst
@@ -1,4 +1,4 @@
-Step 7: Packaging an Installer
+Step 9: Packaging an Installer
==============================
Next suppose that we want to distribute our project to other people so that
@@ -11,7 +11,7 @@ installations and package management features. To accomplish this we will use
CPack to create platform specific installers. Specifically we need to add a
few lines to the bottom of our top-level ``CMakeLists.txt`` file.
-.. literalinclude:: Step8/CMakeLists.txt
+.. literalinclude:: Step10/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-include-CPack
:language: cmake
@@ -38,15 +38,15 @@ binary directory run:
cpack
-To specify the generator, use the ``-G`` option. For multi-config builds, use
-``-C`` to specify the configuration. For example:
+To specify the generator, use the :option:`-G <cpack -G>` option. For multi-config builds,
+use :option:`-C <cpack -C>` to specify the configuration. For example:
.. code-block:: console
cpack -G ZIP -C Debug
For a list of available generators, see :manual:`cpack-generators(7)` or call
-``cpack --help``. An :cpack_gen:`archive generator <CPack Archive Generator>`
+:option:`cpack --help`. An :cpack_gen:`archive generator <CPack Archive Generator>`
like ZIP creates a compressed archive of all *installed* files.
To create an archive of the *full* source tree you would type:
diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst
index 2d5f70e06..1c49c23a5 100644
--- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst
+++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst
@@ -1,5 +1,5 @@
-Step 9: Selecting Static or Shared Libraries
-============================================
+Step 10: Selecting Static or Shared Libraries
+=============================================
In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can
be used to control the default behavior of :command:`add_library`,
@@ -19,7 +19,7 @@ library.
The first step is to update the starting section of the top-level
``CMakeLists.txt`` to look like:
-.. literalinclude:: Step10/CMakeLists.txt
+.. literalinclude:: Step11/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-option-BUILD_SHARED_LIBS
:language: cmake
@@ -33,7 +33,7 @@ explicitly require that SqrtLibrary is built statically.
The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
-.. literalinclude:: Step10/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step11/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_library-STATIC
:language: cmake
@@ -42,7 +42,7 @@ The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
``detail`` namespaces:
-.. literalinclude:: Step10/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step11/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-namespace
:language: c++
@@ -56,7 +56,7 @@ uses ``USE_MYMATH``:
Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
-.. literalinclude:: Step10/MathFunctions/MathFunctions.h
+.. literalinclude:: Step11/MathFunctions/MathFunctions.h
:caption: MathFunctions/MathFunctions.h
:name: MathFunctions/MathFunctions.h
:language: c++
@@ -67,7 +67,7 @@ library that has position independent code. The solution to this is to
explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of
SqrtLibrary to be ``True`` no matter the build type.
-.. literalinclude:: Step10/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step11/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-POSITION_INDEPENDENT_CODE
:language: cmake
diff --git a/Help/guide/tutorial/Step1/CMakeLists.txt b/Help/guide/tutorial/Step1/CMakeLists.txt
new file mode 100644
index 000000000..6fcce90ff
--- /dev/null
+++ b/Help/guide/tutorial/Step1/CMakeLists.txt
@@ -0,0 +1,16 @@
+# TODO 1: Set the minimum required version of CMake to be 3.10
+
+# TODO 2: Create a project named Tutorial
+
+# TODO 7: Set the project version number as 1.0 in the above project command
+
+# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11
+# and the variable CMAKE_CXX_STANDARD_REQUIRED to True
+
+# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to
+# TutorialConfig.h
+
+# TODO 3: Add an executable called Tutorial to the project
+# Hint: Be sure to specify the source file as tutorial.cxx
+
+# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR}
diff --git a/Help/guide/tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step1/TutorialConfig.h.in
new file mode 100644
index 000000000..990bfbd16
--- /dev/null
+++ b/Help/guide/tutorial/Step1/TutorialConfig.h.in
@@ -0,0 +1,2 @@
+// the configured options and settings for Tutorial
+// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR
diff --git a/Help/guide/tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx
index 08323bfac..64d09162c 100644
--- a/Help/guide/tutorial/Step1/tutorial.cxx
+++ b/Help/guide/tutorial/Step1/tutorial.cxx
@@ -1,17 +1,22 @@
// A simple program that computes the square root of a number
#include <cmath>
-#include <cstdlib>
+#include <cstdlib> // TODO 5: Remove this line
#include <iostream>
#include <string>
+// TODO 11: Include TutorialConfig.h
+
int main(int argc, char* argv[])
{
if (argc < 2) {
+ // TODO 12: Create a print statement using Tutorial_VERSION_MAJOR
+ // and Tutorial_VERSION_MINOR
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
// convert input to double
+ // TODO 4: Replace atof(argv[1]) with std::stod(argv[1])
const double inputValue = atof(argv[1]);
// calculate square root
diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt
index 55dc40965..5c661aa22 100644
--- a/Help/guide/tutorial/Step10/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/CMakeLists.txt
@@ -1,29 +1,37 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
-# control where the static and shared libraries are built so that on windows
-# we don't need to tinker with the path to run the executable
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
-option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
-# configure a header file to pass the version number only
+# configure a header file to pass some of the CMake settings
+# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
-add_subdirectory(MathFunctions)
+if(USE_MYMATH)
+ add_subdirectory(MathFunctions)
+ list(APPEND EXTRA_LIBS MathFunctions)
+endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC MathFunctions)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -66,6 +74,7 @@ do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Help/guide/tutorial/Step10/License.txt b/Help/guide/tutorial/Step10/License.txt
index c62d00b9e..85760e591 100644
--- a/Help/guide/tutorial/Step10/License.txt
+++ b/Help/guide/tutorial/Step10/License.txt
@@ -1,2 +1,2 @@
This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
+CMake/Tutorial/Step9...
diff --git a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
index 0bfe20c10..fa7332167 100644
--- a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
@@ -1,55 +1,32 @@
-# add the library that runs
-add_library(MathFunctions MathFunctions.cxx)
+# first we add the executable that generates the table
+add_executable(MakeTable MakeTable.cxx)
+
+# add the command to generate the source code
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+ COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+ DEPENDS MakeTable
+ )
+
+# add the main library
+add_library(MathFunctions
+ mysqrt.cxx
+ ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+ )
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
+# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
- INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
- )
+ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
+ )
-# should we use our own math functions
-option(USE_MYMATH "Use tutorial provided math implementation" ON)
-if(USE_MYMATH)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
- target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
-
- # first we add the executable that generates the table
- add_executable(MakeTable MakeTable.cxx)
-
- # add the command to generate the source code
- add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- DEPENDS MakeTable
- )
-
- # library that just does sqrt
- add_library(SqrtLibrary STATIC
- mysqrt.cxx
- ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- )
-
- # state that we depend on our binary dir to find Table.h
- target_include_directories(SqrtLibrary PRIVATE
- ${CMAKE_CURRENT_BINARY_DIR}
- )
-
- # state that SqrtLibrary need PIC when the default is shared libraries
- set_target_properties(SqrtLibrary PROPERTIES
- POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
- )
-
- target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
-endif()
-
-# define the symbol stating we are using the declspec(dllexport) when
-# building on windows
-target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
-
-# install rules
-set(installable_libs MathFunctions)
-if(TARGET SqrtLibrary)
- list(APPEND installable_libs SqrtLibrary)
-endif()
+# install libs
+set(installable_libs MathFunctions tutorial_compiler_flags)
install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h
index 3fb547b4a..cd36bccff 100644
--- a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h
+++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h
@@ -1,14 +1 @@
-
-#if defined(_WIN32)
-# if defined(EXPORTING_MYMATH)
-# define DECLSPEC __declspec(dllexport)
-# else
-# define DECLSPEC __declspec(dllimport)
-# endif
-#else // non windows
-# define DECLSPEC
-#endif
-
-namespace mathfunctions {
-double DECLSPEC sqrt(double x);
-}
+double mysqrt(double x);
diff --git a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx
index 8153f18be..7d80ee964 100644
--- a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx
@@ -5,8 +5,6 @@
// include the generated table
#include "Table.h"
-namespace mathfunctions {
-namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -33,5 +31,3 @@ double mysqrt(double x)
return result;
}
-}
-}
diff --git a/Help/guide/tutorial/Step10/TutorialConfig.h.in b/Help/guide/tutorial/Step10/TutorialConfig.h.in
index 7e4d7fa1f..e23f5213c 100644
--- a/Help/guide/tutorial/Step10/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step10/TutorialConfig.h.in
@@ -1,3 +1,4 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
+#cmakedefine USE_MYMATH
diff --git a/Help/guide/tutorial/Step10/tutorial.cxx b/Help/guide/tutorial/Step10/tutorial.cxx
index 37a03336c..b3c6a4f43 100644
--- a/Help/guide/tutorial/Step10/tutorial.cxx
+++ b/Help/guide/tutorial/Step10/tutorial.cxx
@@ -1,11 +1,15 @@
// A simple program that computes the square root of a number
+#include <cmath>
#include <iostream>
-#include <sstream>
#include <string>
-#include "MathFunctions.h"
#include "TutorialConfig.h"
+// should we include the MathFunctions header?
+#ifdef USE_MYMATH
+# include "MathFunctions.h"
+#endif
+
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -19,7 +23,12 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
- const double outputValue = mathfunctions::sqrt(inputValue);
+ // which square root function should we use?
+#ifdef USE_MYMATH
+ const double outputValue = mysqrt(inputValue);
+#else
+ const double outputValue = sqrt(inputValue);
+#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt
index 1044748d9..046bfc9a2 100644
--- a/Help/guide/tutorial/Step11/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/CMakeLists.txt
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
+# specify the C++ standard
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
@@ -31,7 +32,7 @@ add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC MathFunctions)
+target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -46,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
@@ -74,6 +75,7 @@ do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Help/guide/tutorial/Step11/License.txt b/Help/guide/tutorial/Step11/License.txt
index c62d00b9e..85760e591 100644
--- a/Help/guide/tutorial/Step11/License.txt
+++ b/Help/guide/tutorial/Step11/License.txt
@@ -1,2 +1,2 @@
This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
+CMake/Tutorial/Step9...
diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
index 0d287ca89..a60fb633b 100644
--- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
@@ -47,13 +47,14 @@ endif()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# define the symbol stating we are using the declspec(dllexport) when
-#building on windows
+# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
-# install rules
+# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step11/tutorial.cxx b/Help/guide/tutorial/Step11/tutorial.cxx
index a4f44d54f..37a03336c 100644
--- a/Help/guide/tutorial/Step11/tutorial.cxx
+++ b/Help/guide/tutorial/Step11/tutorial.cxx
@@ -1,5 +1,6 @@
// A simple program that computes the square root of a number
#include <iostream>
+#include <sstream>
#include <string>
#include "MathFunctions.h"
diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt
index 63f96432d..220ed4b64 100644
--- a/Help/guide/tutorial/Step12/CMakeLists.txt
+++ b/Help/guide/tutorial/Step12/CMakeLists.txt
@@ -37,7 +37,7 @@ add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC MathFunctions)
+target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -80,6 +80,7 @@ do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Help/guide/tutorial/Step12/License.txt b/Help/guide/tutorial/Step12/License.txt
index c62d00b9e..85760e591 100644
--- a/Help/guide/tutorial/Step12/License.txt
+++ b/Help/guide/tutorial/Step12/License.txt
@@ -1,2 +1,2 @@
This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
+CMake/Tutorial/Step9...
diff --git a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
index d5961da4b..a85f3cb70 100644
--- a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
@@ -52,7 +52,7 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
-# install rules
+# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
@@ -60,4 +60,5 @@ endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt
index 7aa59e917..2b96128e1 100644
--- a/Help/guide/tutorial/Step2/CMakeLists.txt
+++ b/Help/guide/tutorial/Step2/CMakeLists.txt
@@ -7,13 +7,36 @@ project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
+# TODO 7: Create a variable USE_MYMATH using option and set default to ON
+
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
+# TODO 8: Use list() and APPEND to create a list of optional libraries
+# called EXTRA_LIBS and a list of optional include directories called
+# EXTRA_INCLUDES. Add the MathFunctions library and source directory to
+# the appropriate lists.
+#
+# Only call add_subdirectory and only add MathFunctions specific values
+# to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true.
+
+# TODO 2: Use add_subdirectory() to add MathFunctions to this project
+
# add the executable
add_executable(Tutorial tutorial.cxx)
+# TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values
+# in target_link_libraries.
+
+# TODO 3: Use target_link_libraries to link the library to our executable
+
+# TODO 4: Add MathFunctions to Tutorial's target_include_directories()
+# Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder!
+
+# TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values
+# in target_include_directories.
+
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
diff --git a/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt
new file mode 100644
index 000000000..b7779b7f2
--- /dev/null
+++ b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt
@@ -0,0 +1,2 @@
+# TODO 1: Add a library called MathFunctions
+# Hint: You will need the add_library command
diff --git a/Help/guide/tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in
index 7e4d7fa1f..6c09e1aca 100644
--- a/Help/guide/tutorial/Step2/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in
@@ -1,3 +1,5 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
+
+// TODO 13: use cmakedefine to define USE_MYMATH
diff --git a/Help/guide/tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx
index 53b081053..87f5e0f64 100644
--- a/Help/guide/tutorial/Step2/tutorial.cxx
+++ b/Help/guide/tutorial/Step2/tutorial.cxx
@@ -5,6 +5,10 @@
#include "TutorialConfig.h"
+// TODO 11: Only include MathFunctions if USE_MYMATH is defined
+
+// TODO 5: Include MathFunctions.h
+
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -18,6 +22,10 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
+ // TODO 12: Use mysqrt if USE_MYMATH is defined and sqrt otherwise
+
+ // TODO 6: Replace sqrt with mysqrt
+
// calculate square root
const double outputValue = sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
diff --git a/Help/guide/tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt
index 1c128165f..007770a37 100644
--- a/Help/guide/tutorial/Step3/CMakeLists.txt
+++ b/Help/guide/tutorial/Step3/CMakeLists.txt
@@ -14,6 +14,8 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON)
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
+# TODO 2: Remove EXTRA_INCLUDES list
+
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
@@ -26,6 +28,8 @@ add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+# TODO 3: Remove use of EXTRA_INCLUDES
+
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
diff --git a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt
index 8b443a659..7bf05e02c 100644
--- a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt
@@ -1 +1,5 @@
add_library(MathFunctions mysqrt.cxx)
+
+# TODO 1: State that anybody linking to MathFunctions needs to include the
+# current source directory, while MathFunctions itself doesn't.
+# Hint: Use target_include_directories with the INTERFACE keyword
diff --git a/Help/guide/tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt
index 38e9b1f72..fa4aab270 100644
--- a/Help/guide/tutorial/Step4/CMakeLists.txt
+++ b/Help/guide/tutorial/Step4/CMakeLists.txt
@@ -1,12 +1,36 @@
+# TODO 4: Update the minimum required version to 3.15
+
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
+# TODO 1: Replace the following code by:
+# * Creating an interface library called tutorial_compiler_flags
+# Hint: use add_library() with the INTERFACE signature
+# * Add compiler feature cxx_std_11 to tutorial_compiler_flags
+# Hint: Use target_compile_features()
+
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
+# TODO 5: Create helper variables to determine which compiler we are using:
+# * Create a new variable gcc_like_cxx that is true if we are using CXX and
+# any of the following compilers: ARMClang, AppleClang, Clang, GNU, LCC
+# * Create a new variable msvc_cxx that is true if we are using CXX and MSVC
+# Hint: Use set() and COMPILE_LANG_AND_ID
+
+# TODO 6: Add warning flag compile options to the interface library
+# tutorial_compiler_flags.
+# * For gcc_like_cxx, add flags -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused
+# * For msvc_cxx, add flags -W3
+# Hint: Use target_compile_options()
+
+# TODO 7: With nested generator expressions, only use the flags for the
+# build-tree
+# Hint: Use BUILD_INTERFACE
+
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -23,6 +47,8 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
+# TODO 2: Link to tutorial_compiler_flags
+
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
diff --git a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt
index 0515852a0..5f7369cae 100644
--- a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt
@@ -5,3 +5,5 @@ add_library(MathFunctions mysqrt.cxx)
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
+
+# TODO 3: Link to tutorial_compiler_flags
diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt
index 82d00c8d4..a8f241adc 100644
--- a/Help/guide/tutorial/Step5/CMakeLists.txt
+++ b/Help/guide/tutorial/Step5/CMakeLists.txt
@@ -1,11 +1,20 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -22,7 +31,7 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -30,37 +39,26 @@ target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
-# add the install targets
-install(TARGETS Tutorial DESTINATION bin)
-install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
- DESTINATION include
- )
+# TODO 3: Install Tutorial in the bin directory
+# Hint: Use the TARGETS and DESTINATION parameters
+
+# TODO 4: Install Tutorial.h to the include directory
+# Hint: Use the FILES and DESTINATION parameters
-# enable testing
-enable_testing()
+# TODO 5: Enable testing
-# does the application run
-add_test(NAME Runs COMMAND Tutorial 25)
+# TODO 6: Add a test called Runs which runs the following command:
+# $ Tutorial 25
-# does the usage message work?
-add_test(NAME Usage COMMAND Tutorial)
-set_tests_properties(Usage
- PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
- )
+# TODO 7: Add a test called Usage which runs the following command:
+# $ Tutorial
+# Make sure the expected output is displayed.
+# Hint: Use the PASS_REGULAR_EXPRESSION property with "Usage.*number"
-# define a function to simplify adding tests
-function(do_test target arg result)
- add_test(NAME Comp${arg} COMMAND ${target} ${arg})
- set_tests_properties(Comp${arg}
- PROPERTIES PASS_REGULAR_EXPRESSION ${result}
- )
-endfunction()
+# TODO 8: Add a test which runs the following command:
+# $ Tutorial 4
+# Make sure the result is correct.
+# Hint: Use the PASS_REGULAR_EXPRESSION property with "4 is 2"
-# do a bunch of result based tests
-do_test(Tutorial 4 "4 is 2")
-do_test(Tutorial 9 "9 is 3")
-do_test(Tutorial 5 "5 is 2.236")
-do_test(Tutorial 7 "7 is 2.645")
-do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is (-nan|nan|0)")
-do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# TODO 9: Add more tests. Create a function called do_test to avoid copy +
+# paste. Test the following values: 4, 9, 5, 7, 25, -25 and 0.00001.
diff --git a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
index b12f27d94..6cd88d7ec 100644
--- a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
@@ -6,6 +6,13 @@ target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
-# install rules
-install(TARGETS MathFunctions DESTINATION lib)
-install(FILES MathFunctions.h DESTINATION include)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
+
+# TODO 1: Create a variable called installable_libs that is a list of all
+# libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags)
+# Then install the installable libraries to the lib folder.
+# Hint: Use the TARGETS and DESTINATION parameters
+
+# TODO 2: Install the library headers to the include folder.
+# Hint: Use the FILES and DESTINATION parameters
diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt
index 82d00c8d4..da9e8521e 100644
--- a/Help/guide/tutorial/Step6/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/CMakeLists.txt
@@ -1,11 +1,20 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -22,7 +31,7 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
diff --git a/Help/guide/tutorial/Step6/CTestConfig.cmake b/Help/guide/tutorial/Step6/CTestConfig.cmake
new file mode 100644
index 000000000..73efdb1f6
--- /dev/null
+++ b/Help/guide/tutorial/Step6/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
index 42e098af8..b4724c4a1 100644
--- a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
@@ -6,29 +6,11 @@ target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
-# does this system provide the log and exp functions?
-include(CheckCXXSourceCompiles)
-check_cxx_source_compiles("
- #include <cmath>
- int main() {
- std::log(1.0);
- return 0;
- }
-" HAVE_LOG)
-check_cxx_source_compiles("
- #include <cmath>
- int main() {
- std::exp(1.0);
- return 0;
- }
-" HAVE_EXP)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
-# add compile definitions
-if(HAVE_LOG AND HAVE_EXP)
- target_compile_definitions(MathFunctions
- PRIVATE "HAVE_LOG" "HAVE_EXP")
-endif()
-
-# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+# install libs
+set(installable_libs MathFunctions tutorial_compiler_flags)
+install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
deleted file mode 100644
index ee585568c..000000000
--- a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// A simple program that builds a sqrt table
-#include <cmath>
-#include <fstream>
-#include <iostream>
-
-int main(int argc, char* argv[])
-{
- // make sure we have enough arguments
- if (argc < 2) {
- return 1;
- }
-
- std::ofstream fout(argv[1], std::ios_base::out);
- const bool fileOpen = fout.is_open();
- if (fileOpen) {
- fout << "double sqrtTable[] = {" << std::endl;
- for (int i = 0; i < 10; ++i) {
- fout << sqrt(static_cast<double>(i)) << "," << std::endl;
- }
- // close the table with a zero
- fout << "0};" << std::endl;
- fout.close();
- }
- return fileOpen ? 0 : 1; // return 0 if wrote the file
-}
diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
index 7eecd26b5..abe767d5a 100644
--- a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
@@ -1,4 +1,3 @@
-#include <cmath>
#include <iostream>
#include "MathFunctions.h"
@@ -10,12 +9,6 @@ double mysqrt(double x)
return 0;
}
- // if we have both log and exp then use them
-#if defined(HAVE_LOG) && defined(HAVE_EXP)
- double result = std::exp(std::log(x) * 0.5);
- std::cout << "Computing sqrt of " << x << " to be " << result
- << " using log and exp" << std::endl;
-#else
double result = x;
// do ten iterations
@@ -27,6 +20,5 @@ double mysqrt(double x)
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
-#endif
return result;
}
diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt
index 82d00c8d4..d26a90cee 100644
--- a/Help/guide/tutorial/Step7/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/CMakeLists.txt
@@ -1,11 +1,20 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -22,7 +31,7 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -37,7 +46,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
diff --git a/Help/guide/tutorial/Step7/CTestConfig.cmake b/Help/guide/tutorial/Step7/CTestConfig.cmake
new file mode 100644
index 000000000..73efdb1f6
--- /dev/null
+++ b/Help/guide/tutorial/Step7/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step7/License.txt b/Help/guide/tutorial/Step7/License.txt
deleted file mode 100644
index c62d00b9e..000000000
--- a/Help/guide/tutorial/Step7/License.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
diff --git a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
index 9ede4b327..b4724c4a1 100644
--- a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
@@ -1,29 +1,16 @@
-# first we add the executable that generates the table
-add_executable(MakeTable MakeTable.cxx)
-
-# add the command to generate the source code
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- DEPENDS MakeTable
- )
-
-# add the main library
-add_library(MathFunctions
- mysqrt.cxx
- ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- )
+add_library(MathFunctions mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
-# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
-# TutorialConfig.h include is an implementation detail
-# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
- PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
-# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
+
+# install libs
+set(installable_libs MathFunctions tutorial_compiler_flags)
+install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx
deleted file mode 100644
index ee585568c..000000000
--- a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// A simple program that builds a sqrt table
-#include <cmath>
-#include <fstream>
-#include <iostream>
-
-int main(int argc, char* argv[])
-{
- // make sure we have enough arguments
- if (argc < 2) {
- return 1;
- }
-
- std::ofstream fout(argv[1], std::ios_base::out);
- const bool fileOpen = fout.is_open();
- if (fileOpen) {
- fout << "double sqrtTable[] = {" << std::endl;
- for (int i = 0; i < 10; ++i) {
- fout << sqrt(static_cast<double>(i)) << "," << std::endl;
- }
- // close the table with a zero
- fout << "0};" << std::endl;
- fout.close();
- }
- return fileOpen ? 0 : 1; // return 0 if wrote the file
-}
diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
index 7d80ee964..abe767d5a 100644
--- a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
@@ -2,9 +2,6 @@
#include "MathFunctions.h"
-// include the generated table
-#include "Table.h"
-
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -12,12 +9,7 @@ double mysqrt(double x)
return 0;
}
- // use the table to help find an initial value
double result = x;
- if (x >= 1 && x < 10) {
- std::cout << "Use the table to help find an initial value " << std::endl;
- result = sqrtTable[static_cast<int>(x)];
- }
// do ten iterations
for (int i = 0; i < 10; ++i) {
@@ -28,6 +20,5 @@ double mysqrt(double x)
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
-
return result;
}
diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt
index 4c78b94c0..cb87281b9 100644
--- a/Help/guide/tutorial/Step8/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/CMakeLists.txt
@@ -1,11 +1,21 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
+
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -22,7 +32,7 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -37,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
@@ -64,11 +74,3 @@ do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-# setup installer
-include(InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-set(CPACK_SOURCE_GENERATOR "TGZ")
-include(CPack)
diff --git a/Help/guide/tutorial/Step8/License.txt b/Help/guide/tutorial/Step8/License.txt
deleted file mode 100644
index c62d00b9e..000000000
--- a/Help/guide/tutorial/Step8/License.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
diff --git a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
index 9ede4b327..f81b56340 100644
--- a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
@@ -1,29 +1,39 @@
-# first we add the executable that generates the table
-add_executable(MakeTable MakeTable.cxx)
-
-# add the command to generate the source code
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- DEPENDS MakeTable
- )
-
-# add the main library
-add_library(MathFunctions
- mysqrt.cxx
- ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- )
+add_library(MathFunctions mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
-# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
-# TutorialConfig.h include is an implementation detail
-# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
- PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
-# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
+
+# does this system provide the log and exp functions?
+include(CheckCXXSourceCompiles)
+check_cxx_source_compiles("
+ #include <cmath>
+ int main() {
+ std::log(1.0);
+ return 0;
+ }
+" HAVE_LOG)
+check_cxx_source_compiles("
+ #include <cmath>
+ int main() {
+ std::exp(1.0);
+ return 0;
+ }
+" HAVE_EXP)
+
+# add compile definitions
+if(HAVE_LOG AND HAVE_EXP)
+ target_compile_definitions(MathFunctions
+ PRIVATE "HAVE_LOG" "HAVE_EXP")
+endif()
+
+# install libs
+set(installable_libs MathFunctions tutorial_compiler_flags)
+install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx
index 7d80ee964..7eecd26b5 100644
--- a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx
@@ -1,10 +1,8 @@
+#include <cmath>
#include <iostream>
#include "MathFunctions.h"
-// include the generated table
-#include "Table.h"
-
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -12,12 +10,13 @@ double mysqrt(double x)
return 0;
}
- // use the table to help find an initial value
+ // if we have both log and exp then use them
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+ double result = std::exp(std::log(x) * 0.5);
+ std::cout << "Computing sqrt of " << x << " to be " << result
+ << " using log and exp" << std::endl;
+#else
double result = x;
- if (x >= 1 && x < 10) {
- std::cout << "Use the table to help find an initial value " << std::endl;
- result = sqrtTable[static_cast<int>(x)];
- }
// do ten iterations
for (int i = 0; i < 10; ++i) {
@@ -28,6 +27,6 @@ double mysqrt(double x)
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
-
+#endif
return result;
}
diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt
index 6bae26e42..d26a90cee 100644
--- a/Help/guide/tutorial/Step9/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/CMakeLists.txt
@@ -1,11 +1,20 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+ "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+ "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
@@ -22,7 +31,7 @@ endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -64,10 +73,3 @@ do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-include(InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-set(CPACK_SOURCE_GENERATOR "TGZ")
-include(CPack)
diff --git a/Help/guide/tutorial/Step9/License.txt b/Help/guide/tutorial/Step9/License.txt
index c62d00b9e..85760e591 100644
--- a/Help/guide/tutorial/Step9/License.txt
+++ b/Help/guide/tutorial/Step9/License.txt
@@ -1,2 +1,2 @@
This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
+CMake/Tutorial/Step9...
diff --git a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
index 50f0701fe..8e04f9749 100644
--- a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
@@ -16,12 +16,19 @@ add_library(MathFunctions
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
+# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
+# TutorialConfig.h include is an implementation detail
# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
-# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+# link our compiler flags interface library
+target_link_libraries(MathFunctions tutorial_compiler_flags)
+
+# install libs
+set(installable_libs MathFunctions tutorial_compiler_flags)
+install(TARGETS ${installable_libs} DESTINATION lib)
+# install include headers
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx
deleted file mode 100644
index 014530062..000000000
--- a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx
+++ /dev/null
@@ -1,19 +0,0 @@
-
-#include "MathFunctions.h"
-
-#include <cmath>
-
-#ifdef USE_MYMATH
-# include "mysqrt.h"
-#endif
-
-namespace mathfunctions {
-double sqrt(double x)
-{
-#ifdef USE_MYMATH
- return detail::mysqrt(x);
-#else
- return std::sqrt(x);
-#endif
-}
-}
diff --git a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h
deleted file mode 100644
index e1c42ef0c..000000000
--- a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h
+++ /dev/null
@@ -1,6 +0,0 @@
-
-namespace mathfunctions {
-namespace detail {
-double mysqrt(double x);
-}
-}
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 09553cb28..1ab00093d 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -24,13 +24,13 @@ provides the complete solution for the previous step.
A Basic Starting Point
Adding a Library
Adding Usage Requirements for a Library
+ Adding Generator Expressions
Installing and Testing
+ Adding Support for a Testing Dashboard
Adding System Introspection
Adding a Custom Command and Generated File
Packaging an Installer
- Adding Support for a Testing Dashboard
Selecting Static or Shared Libraries
- Adding Generator Expressions
Adding Export Configuration
Packaging Debug and Release
diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst
index ba8196bda..335599223 100644
--- a/Help/guide/user-interaction/index.rst
+++ b/Help/guide/user-interaction/index.rst
@@ -71,8 +71,8 @@ The CMake tooling may report warnings which are intended
for the provider of the software, not intended for the
consumer of the software. Such warnings end with "This
warning is for project developers". Users may disable
-such warnings by passing the ``-Wno-dev`` flag to
-:manual:`cmake(1)`.
+such warnings by passing the :option:`-Wno-dev <cmake -Wno-dev>`
+flag to :manual:`cmake(1)`.
cmake-gui tool
--------------
@@ -153,13 +153,13 @@ platform. Usually, the default generator is sufficient
to allow the user to proceed to build the software.
The user may override the default generator with
-the ``-G`` option:
+the :option:`-G <cmake -G>` option:
.. code-block:: console
$ cmake .. -G Ninja
-The output of ``cmake --help`` includes a list of
+The output of :option:`cmake --help` includes a list of
:manual:`generators <cmake-generators(7)>` available
for the user to choose from. Note that generator
names are case sensitive.
@@ -196,7 +196,8 @@ VisualC++ compiler, or a combination of the two:
$ cmake .. -G "Visual Studio 16 2019"
Visual Studio generators can target different architectures.
-One can specify the target architecture using the `-A` option:
+One can specify the target architecture using the
+:option:`-A <cmake -A>` option:
.. code-block:: console
@@ -214,8 +215,8 @@ generator to use, typically a choice between a ``Makefile``
or a ``Ninja`` based generator.
Note that it is not possible to change the generator
-with ``-G`` after the first invocation of CMake. To
-change the generator, the build directory must be
+with :option:`-G <cmake -G>` after the first invocation of CMake.
+To change the generator, the build directory must be
deleted and the build must be started from scratch.
When generating Visual Studio project and solutions
@@ -223,7 +224,7 @@ files several other options are available to use when
initially running :manual:`cmake(1)`.
The Visual Studio toolset can be specified with the
-``-T`` option:
+:option:`cmake -T` option:
.. code-block:: console
@@ -232,9 +233,9 @@ The Visual Studio toolset can be specified with the
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp
-Whereas the ``-A`` option specifies the _target_
-architecture, the ``-T`` option can be used to specify
-details of the toolchain used. For example, `-Thost=x64`
+Whereas the :option:`-A <cmake -A>` option specifies the _target_
+architecture, the :option:`-T <cmake -T>` option can be used to specify
+details of the toolchain used. For example, ``-Thost=x64``
can be given to select the 64-bit version of the host
tools. The following demonstrates how to use 64-bit
tools and also build for a 64-bit target architecture:
@@ -337,7 +338,7 @@ or later on a subsequent invocation of
$ cd build
$ cmake . -DCMAKE_BUILD_TYPE=Debug
-The ``-U`` flag may be used to unset variables
+The :option:`-U <cmake -U>` flag may be used to unset variables
on the :manual:`cmake(1)` command line:
.. code-block:: console
@@ -351,7 +352,7 @@ on the command line can be modified using the
The :manual:`cmake(1)` tool allows specifying a
file to use to populate the initial cache using
-the ``-C`` option. This can be useful to simplify
+the :option:`-C <cmake -C>` option. This can be useful to simplify
commands and scripts which repeatedly require the
same cache entries.
@@ -427,10 +428,10 @@ Using presets on the command-line
---------------------------------
When using the :manual:`cmake(1)` command line tool, a
-preset can be invoked by using the ``--preset`` option. If
-``--preset`` is specified, the generator and build
-directory are not required, but can be specified to
-override them. For example, if you have the following
+preset can be invoked by using the :option:`--preset <cmake --preset>`
+option. If :option:`--preset <cmake --preset>` is specified,
+the generator and build directory are not required, but can be
+specified to override them. For example, if you have the following
``CMakePresets.json`` file:
.. code-block:: json
@@ -502,23 +503,25 @@ command may be invoked in the build directory:
$ cmake --build .
-The ``--build`` flag enables a particular mode of
-operation for the :manual:`cmake(1)` tool. It invokes
-the :variable:`CMAKE_MAKE_PROGRAM` command associated
-with the :manual:`generator <cmake-generators(7)>`, or
+The :option:`--build <cmake --build>` flag enables a
+particular mode of operation for the :manual:`cmake(1)`
+tool. It invokes the :variable:`CMAKE_MAKE_PROGRAM`
+command associated with the
+:manual:`generator <cmake-generators(7)>`, or
the build tool configured by the user.
-The ``--build`` mode also accepts the parameter
-``--target`` to specify a particular target to build,
-for example a particular library, executable or
-custom target, or a particular special target like
-``install``:
+The :option:`--build <cmake --build>` mode also accepts
+the parameter :option:`--target <cmake--build --target>` to
+specify a particular target to build, for example a
+particular library, executable or custom target, or a
+particular special target like ``install``:
.. code-block:: console
$ cmake --build . --target myexe
-The ``--build`` mode also accepts a ``--config`` parameter
+The :option:`--build <cmake --build>` mode also accepts a
+:option:`--config <cmake--build --config>` parameter
in the case of multi-config generators to specify which
particular configuration to build:
@@ -526,23 +529,23 @@ particular configuration to build:
$ cmake --build . --target myexe --config Release
-The ``--config`` option has no effect if the generator
-generates a buildsystem specific to a configuration which
-is chosen when invoking cmake with the
-:variable:`CMAKE_BUILD_TYPE` variable.
+The :option:`--config <cmake--build --config>` option has no
+effect if the generator generates a buildsystem specific
+to a configuration which is chosen when invoking cmake
+with the :variable:`CMAKE_BUILD_TYPE` variable.
Some buildsystems omit details of command lines invoked
-during the build. The ``--verbose`` flag can be used to
-cause those command lines to be shown:
+during the build. The :option:`--verbose <cmake--build --verbose>`
+flag can be used to cause those command lines to be shown:
.. code-block:: console
$ cmake --build . --target myexe --verbose
-The ``--build`` mode can also pass particular command
-line options to the underlying build tool by listing
-them after ``--``. This can be useful to specify
-options to the build tool, such as to continue the
+The :option:`--build <cmake --build>` mode can also pass
+particular command line options to the underlying build
+tool by listing them after ``--``. This can be useful
+to specify options to the build tool, such as to continue the
build after a failed job, where CMake does not
provide a high-level user interface.
@@ -638,9 +641,9 @@ building the ``foo.i`` target will preprocess both files.
Specifying a Build Program
--------------------------
-The program invoked by the ``--build`` mode is determined
-by the :variable:`CMAKE_MAKE_PROGRAM` variable. For most
-generators, the particular program does not need to be
+The program invoked by the :option:`--build <cmake --build>`
+mode is determined by the :variable:`CMAKE_MAKE_PROGRAM` variable.
+For most generators, the particular program does not need to be
configured.
===================== =========================== ===========================
@@ -661,7 +664,8 @@ The ``jom`` tool is capable of reading makefiles of the
``NMake`` flavor and building in parallel, while the
``nmake`` tool always builds serially. After generating
with the :generator:`NMake Makefiles` generator a user
-can run ``jom`` instead of ``nmake``. The ``--build``
+can run ``jom`` instead of ``nmake``. The
+:option:`--build <cmake --build>`
mode would also use ``jom`` if the
:variable:`CMAKE_MAKE_PROGRAM` was set to ``jom`` while
using the :generator:`NMake Makefiles` generator, and
@@ -671,7 +675,7 @@ and use it as the :variable:`CMAKE_MAKE_PROGRAM`. For
completeness, ``nmake`` is an alternative tool which
can process the output of the
:generator:`NMake Makefiles JOM` generator, but doing
-so would be a pessimisation.
+so would be a pessimization.
Software Installation
=====================
@@ -745,8 +749,8 @@ run only tests without ``Qt`` in their name:
$ ctest -E Qt
-Tests can be run in parallel by passing ``-j`` arguments
-to :manual:`ctest(1)`:
+Tests can be run in parallel by passing :option:`-j <ctest -j>`
+arguments to :manual:`ctest(1)`:
.. code-block:: console
@@ -754,14 +758,15 @@ to :manual:`ctest(1)`:
The environment variable :envvar:`CTEST_PARALLEL_LEVEL`
can alternatively be set to avoid the need to pass
-``-j``.
+:option:`-j <ctest -j>`.
By default :manual:`ctest(1)` does not print the output
-from the tests. The command line argument ``-V`` (or
-``--verbose``) enables verbose mode to print the
+from the tests. The command line argument :option:`-V <ctest -V>`
+(or ``--verbose``) enables verbose mode to print the
output from all tests.
-The ``--output-on-failure`` option prints the test
-output for failing tests only. The environment variable
-:envvar:`CTEST_OUTPUT_ON_FAILURE`
+The :option:`--output-on-failure <ctest --output-on-failure>`
+option prints the test output for failing tests only.
+The environment variable :envvar:`CTEST_OUTPUT_ON_FAILURE`
can be set to ``1`` as an alternative to passing the
-``--output-on-failure`` option to :manual:`ctest(1)`.
+:option:`--output-on-failure <ctest --output-on-failure>`
+option to :manual:`ctest(1)`.
diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index 8e23b7711..94adac861 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -1,12 +1,15 @@
-``-S <path-to-source>``
+.. option:: -S <path-to-source>
+
Path to root directory of the CMake project to build.
-``-B <path-to-build>``
+.. option:: -B <path-to-build>
+
Path to directory which CMake will use as the root of build directory.
If the directory doesn't already exist CMake will make it.
-``-C <initial-cache>``
+.. option:: -C <initial-cache>
+
Pre-load a script to populate the cache.
When CMake is first run in an empty build tree, it creates a
@@ -21,7 +24,8 @@
References to :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR`
within the script evaluate to the top-level source and build tree.
-``-D <var>:<type>=<value>, -D <var>=<value>``
+.. option:: -D <var>:<type>=<value>, -D <var>=<value>
+
Create or update a CMake ``CACHE`` entry.
When CMake is first run in an empty build tree, it creates a
@@ -41,7 +45,27 @@
This option may also be given as a single argument:
``-D<var>:<type>=<value>`` or ``-D<var>=<value>``.
-``-U <globbing_expr>``
+ It's important to note that the order of ``-C`` and ``-D`` arguments is
+ significant. They will be carried out in the order they are listed, with the
+ last argument taking precedence over the previous ones. For example, if you
+ specify ``-DCMAKE_BUILD_TYPE=Debug``, followed by a ``-C`` argument with a
+ file that calls:
+
+ .. code-block:: cmake
+
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
+
+ then the ``-C`` argument will take precedence, and ``CMAKE_BUILD_TYPE`` will
+ be set to ``Release``. However, if the ``-D`` argument comes after the ``-C``
+ argument, it will be set to ``Debug``.
+
+ If a ``set(... CACHE ...)`` call in the ``-C`` file does not use ``FORCE``,
+ and a ``-D`` argument sets the same variable, the ``-D`` argument will take
+ precedence regardless of order because of the nature of non-``FORCE``
+ ``set(... CACHE ...)`` calls.
+
+.. option:: -U <globbing_expr>
+
Remove matching entries from CMake ``CACHE``.
This option may be used to remove one or more variables from the
@@ -51,7 +75,8 @@
Use with care, you can make your ``CMakeCache.txt`` non-working.
-``-G <generator-name>``
+.. option:: -G <generator-name>
+
Specify a build system generator.
CMake may support multiple native build systems on certain
@@ -62,73 +87,85 @@
If not specified, CMake checks the :envvar:`CMAKE_GENERATOR` environment
variable and otherwise falls back to a builtin default selection.
-``-T <toolset-spec>``
+.. option:: -T <toolset-spec>
+
Toolset specification for the generator, if supported.
Some CMake generators support a toolset specification to tell
the native build system how to choose a compiler. See the
:variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
-``-A <platform-name>``
+.. option:: -A <platform-name>
+
Specify platform name if supported by generator.
Some CMake generators support a platform name to be given to the
native build system to choose a compiler or SDK. See the
:variable:`CMAKE_GENERATOR_PLATFORM` variable for details.
-``--toolchain <path-to-file>``
+.. option:: --toolchain <path-to-file>
+
Specify the cross compiling toolchain file, equivalent to setting
:variable:`CMAKE_TOOLCHAIN_FILE` variable.
-``--install-prefix <directory>``
+.. option:: --install-prefix <directory>
+
Specify the installation directory, used by the
:variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path.
-``-Wno-dev``
+.. option:: -Wno-dev
+
Suppress developer warnings.
Suppress warnings that are meant for the author of the
``CMakeLists.txt`` files. By default this will also turn off
deprecation warnings.
-``-Wdev``
+.. option:: -Wdev
+
Enable developer warnings.
Enable warnings that are meant for the author of the ``CMakeLists.txt``
files. By default this will also turn on deprecation warnings.
-``-Werror=dev``
- Make developer warnings errors.
-
- Make warnings that are meant for the author of the ``CMakeLists.txt`` files
- errors. By default this will also turn on deprecated warnings as errors.
+.. option:: -Wdeprecated
-``-Wno-error=dev``
- Make developer warnings not errors.
-
- Make warnings that are meant for the author of the ``CMakeLists.txt`` files not
- errors. By default this will also turn off deprecated warnings as errors.
-
-``-Wdeprecated``
Enable deprecated functionality warnings.
Enable warnings for usage of deprecated functionality, that are meant
for the author of the ``CMakeLists.txt`` files.
-``-Wno-deprecated``
+.. option:: -Wno-deprecated
+
Suppress deprecated functionality warnings.
Suppress warnings for usage of deprecated functionality, that are meant
for the author of the ``CMakeLists.txt`` files.
-``-Werror=deprecated``
- Make deprecated macro and function warnings errors.
+.. option:: -Werror=<what>
+
+ Treat CMake warnings as errors. ``<what>`` must be one of the following:
+
+ ``dev``
+ Make developer warnings errors.
+
+ Make warnings that are meant for the author of the ``CMakeLists.txt`` files
+ errors. By default this will also turn on deprecated warnings as errors.
+
+ ``deprecated``
+ Make deprecated macro and function warnings errors.
+
+ Make warnings for usage of deprecated macros and functions, that are meant
+ for the author of the ``CMakeLists.txt`` files, errors.
+
+.. option:: -Wno-error=<what>
- Make warnings for usage of deprecated macros and functions, that are meant
- for the author of the ``CMakeLists.txt`` files, errors.
+ Do not treat CMake warnings as errors. ``<what>`` must be one of the following:
-``-Wno-error=deprecated``
- Make deprecated macro and function warnings not errors.
+ ``dev``
+ Make warnings that are meant for the author of the ``CMakeLists.txt`` files not
+ errors. By default this will also turn off deprecated warnings as errors.
- Make warnings for usage of deprecated macros and functions, that are meant
- for the author of the ``CMakeLists.txt`` files, not errors.
+ ``deprecated``
+ Make warnings for usage of deprecated macros and functions, that are meant
+ for the author of the ``CMakeLists.txt`` files, not errors.
diff --git a/Help/manual/OPTIONS_HELP.txt b/Help/manual/OPTIONS_HELP.txt
index feeca7dc3..78ee24553 100644
--- a/Help/manual/OPTIONS_HELP.txt
+++ b/Help/manual/OPTIONS_HELP.txt
@@ -1,134 +1,152 @@
-.. |file| replace:: The help is printed to a named <f>ile if given.
+.. |file| replace:: The output is printed to a named ``<file>`` if given.
+
+.. option:: -version [<file>], --version [<file>], /V [<file>]
+
+ Show program name/version banner and exit.
+ |file|
+
+.. option:: -h, -H, --help, -help, -usage, /?
-``--help,-help,-usage,-h,-H,/?``
Print usage information and exit.
Usage describes the basic command line interface and its options.
-``--version,-version,/V [<f>]``
- Show program name/version banner and exit.
+.. option:: --help-full [<file>]
- If a file is specified, the version is written into it.
- |file|
-
-``--help-full [<f>]``
Print all help manuals and exit.
All manuals are printed in a human-readable text format.
|file|
-``--help-manual <man> [<f>]``
+.. option:: --help-manual <man> [<file>]
+
Print one help manual and exit.
The specified manual is printed in a human-readable text format.
|file|
-``--help-manual-list [<f>]``
+.. option:: --help-manual-list [<file>]
+
List help manuals available and exit.
The list contains all manuals for which help may be obtained by
using the ``--help-manual`` option followed by a manual name.
|file|
-``--help-command <cmd> [<f>]``
+.. option:: --help-command <cmd> [<file>]
+
Print help for one command and exit.
The :manual:`cmake-commands(7)` manual entry for ``<cmd>`` is
printed in a human-readable text format.
|file|
-``--help-command-list [<f>]``
+.. option:: --help-command-list [<file>]
+
List commands with help available and exit.
The list contains all commands for which help may be obtained by
using the ``--help-command`` option followed by a command name.
|file|
-``--help-commands [<f>]``
+.. option:: --help-commands [<file>]
+
Print cmake-commands manual and exit.
The :manual:`cmake-commands(7)` manual is printed in a
human-readable text format.
|file|
-``--help-module <mod> [<f>]``
+.. option:: --help-module <mod> [<file>]
+
Print help for one module and exit.
The :manual:`cmake-modules(7)` manual entry for ``<mod>`` is printed
in a human-readable text format.
|file|
-``--help-module-list [<f>]``
+.. option:: --help-module-list [<file>]
+
List modules with help available and exit.
The list contains all modules for which help may be obtained by
using the ``--help-module`` option followed by a module name.
|file|
-``--help-modules [<f>]``
+.. option:: --help-modules [<file>]
+
Print cmake-modules manual and exit.
The :manual:`cmake-modules(7)` manual is printed in a human-readable
text format.
|file|
-``--help-policy <cmp> [<f>]``
+.. option:: --help-policy <cmp> [<file>]
+
Print help for one policy and exit.
The :manual:`cmake-policies(7)` manual entry for ``<cmp>`` is
printed in a human-readable text format.
|file|
-``--help-policy-list [<f>]``
+.. option:: --help-policy-list [<file>]
+
List policies with help available and exit.
The list contains all policies for which help may be obtained by
using the ``--help-policy`` option followed by a policy name.
|file|
-``--help-policies [<f>]``
+.. option:: --help-policies [<file>]
+
Print cmake-policies manual and exit.
The :manual:`cmake-policies(7)` manual is printed in a
human-readable text format.
|file|
-``--help-property <prop> [<f>]``
+.. option:: --help-property <prop> [<file>]
+
Print help for one property and exit.
The :manual:`cmake-properties(7)` manual entries for ``<prop>`` are
printed in a human-readable text format.
|file|
-``--help-property-list [<f>]``
+.. option:: --help-property-list [<file>]
+
List properties with help available and exit.
The list contains all properties for which help may be obtained by
using the ``--help-property`` option followed by a property name.
|file|
-``--help-properties [<f>]``
+.. option:: --help-properties [<file>]
+
Print cmake-properties manual and exit.
The :manual:`cmake-properties(7)` manual is printed in a
human-readable text format.
|file|
-``--help-variable <var> [<f>]``
+.. option:: --help-variable <var> [<file>]
+
Print help for one variable and exit.
The :manual:`cmake-variables(7)` manual entry for ``<var>`` is
printed in a human-readable text format.
|file|
-``--help-variable-list [<f>]``
+.. option:: --help-variable-list [<file>]
+
List variables with help available and exit.
The list contains all variables for which help may be obtained by
using the ``--help-variable`` option followed by a variable name.
|file|
-``--help-variables [<f>]``
+.. option:: --help-variables [<file>]
+
Print cmake-variables manual and exit.
The :manual:`cmake-variables(7)` manual is printed in a
diff --git a/Help/manual/ccmake.1.rst b/Help/manual/ccmake.1.rst
index 60d45a35d..cd66d5122 100644
--- a/Help/manual/ccmake.1.rst
+++ b/Help/manual/ccmake.1.rst
@@ -8,7 +8,7 @@ Synopsis
.. parsed-literal::
- ccmake [<options>] {<path-to-source> | <path-to-existing-build>}
+ ccmake [<options>] <path-to-source | path-to-existing-build>
Description
===========
@@ -27,6 +27,8 @@ native tool on their platform.
Options
=======
+.. program:: ccmake
+
.. include:: OPTIONS_BUILD.txt
.. include:: OPTIONS_HELP.txt
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index bceff2d89..b14160c3c 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -257,7 +257,7 @@ targets in multiple different directories convenient through use of the
Transitive Usage Requirements
-----------------------------
-The usage requirements of a target can transitively propagate to dependents.
+The usage requirements of a target can transitively propagate to the dependents.
The :command:`target_link_libraries` command has ``PRIVATE``,
``INTERFACE`` and ``PUBLIC`` keywords to control the propagation.
@@ -279,8 +279,10 @@ The :command:`target_link_libraries` command has ``PRIVATE``,
# consumer is compiled with -DUSING_ARCHIVE_LIB
target_link_libraries(consumer archiveExtras)
-Because ``archive`` is a ``PUBLIC`` dependency of ``archiveExtras``, the
-usage requirements of it are propagated to ``consumer`` too. Because
+Because the ``archive`` is a ``PUBLIC`` dependency of ``archiveExtras``, the
+usage requirements of it are propagated to ``consumer`` too.
+
+Because
``serialization`` is a ``PRIVATE`` dependency of ``archiveExtras``, the usage
requirements of it are not propagated to ``consumer``.
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index 036fa8fe5..0f35632d5 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -15,6 +15,7 @@ These commands are always available.
.. toctree::
:maxdepth: 1
+ /command/block
/command/break
/command/cmake_host_system_information
/command/cmake_language
@@ -26,6 +27,7 @@ These commands are always available.
/command/continue
/command/else
/command/elseif
+ /command/endblock
/command/endforeach
/command/endfunction
/command/endif
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index 737b22cdd..50fcf756c 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -21,6 +21,8 @@ Environment Variables that Change Behavior
:maxdepth: 1
/envvar/CMAKE_PREFIX_PATH
+ /envvar/SSL_CERT_DIR
+ /envvar/SSL_CERT_FILE
Environment Variables that Control the Build
============================================
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 7a6188aaf..69e3f20e5 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -594,6 +594,10 @@ Configuration Expressions
expression when it is evaluated on a property of an :prop_tgt:`IMPORTED`
target.
+ .. versionchanged:: 3.19
+ Multiple configurations can be specified for ``cfgs``.
+ CMake 3.18 and earlier only accepted a single configuration.
+
.. genex:: $<OUTPUT_CONFIG:...>
.. versionadded:: 3.20
@@ -627,9 +631,8 @@ Platform
.. genex:: $<PLATFORM_ID:platform_ids>
- where ``platform_ids`` is a comma-separated list.
``1`` if CMake's platform id matches any one of the entries in
- ``platform_ids``, otherwise ``0``.
+ comma-separated list ``platform_ids``, otherwise ``0``.
See also the :variable:`CMAKE_SYSTEM_NAME` variable.
Compiler Version
@@ -844,10 +847,15 @@ related to most of the expressions in this sub-section.
.. versionadded:: 3.3
- ``1`` when the language used for compilation unit matches any of the entries
- in ``languages``, otherwise ``0``. This expression may be used to specify
- compile options, compile definitions, and include directories for source
- files of a particular language in a target. For example:
+ .. versionchanged:: 3.15
+ Multiple languages can be specified for ``languages``.
+ CMake 3.14 and earlier only accepted a single language.
+
+ ``1`` when the language used for compilation unit matches any of the
+ comma-separated entries in ``languages``, otherwise ``0``. This expression
+ may be used to specify compile options, compile definitions, and include
+ directories for source files of a particular language in a target. For
+ example:
.. code-block:: cmake
@@ -892,8 +900,8 @@ related to most of the expressions in this sub-section.
``1`` when the language used for compilation unit matches ``language`` and
CMake's compiler id of the ``language`` compiler matches any one of the
- entries in ``compiler_ids``, otherwise ``0``. This expression is a short form
- for the combination of ``$<COMPILE_LANGUAGE:language>`` and
+ comma-separated entries in ``compiler_ids``, otherwise ``0``. This expression
+ is a short form for the combination of ``$<COMPILE_LANGUAGE:language>`` and
``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
compile options, compile definitions, and include directories for source
files of a particular language and compiler combination in a target.
@@ -967,10 +975,10 @@ Linker Language And ID
.. versionadded:: 3.18
- ``1`` when the language used for link step matches any of the entries
- in ``languages``, otherwise ``0``. This expression may be used to specify
- link libraries, link options, link directories and link dependencies of a
- particular language in a target. For example:
+ ``1`` when the language used for link step matches any of the comma-separated
+ entries in ``languages``, otherwise ``0``. This expression may be used to
+ specify link libraries, link options, link directories and link dependencies
+ of a particular language in a target. For example:
.. code-block:: cmake
@@ -1033,9 +1041,9 @@ Linker Language And ID
.. versionadded:: 3.18
``1`` when the language used for link step matches ``language`` and the
- CMake's compiler id of the language linker matches any one of the entries
- in ``compiler_ids``, otherwise ``0``. This expression is a short form for the
- combination of ``$<LINK_LANGUAGE:language>`` and
+ CMake's compiler id of the language linker matches any one of the comma-separated
+ entries in ``compiler_ids``, otherwise ``0``. This expression is a short form
+ for the combination of ``$<LINK_LANGUAGE:language>`` and
``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
link libraries, link options, link directories and link dependencies of a
particular language and linker combination in a target. For example:
diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst
index 034e2186a..ed5bbbf6c 100644
--- a/Help/manual/cmake-generators.7.rst
+++ b/Help/manual/cmake-generators.7.rst
@@ -18,11 +18,11 @@ as a variant of some of the `Command-Line Build Tool Generators`_ to
produce project files for an auxiliary IDE.
CMake Generators are platform-specific so each may be available only
-on certain platforms. The :manual:`cmake(1)` command-line tool ``--help``
-output lists available generators on the current platform. Use its ``-G``
-option to specify the generator for a new build tree.
-The :manual:`cmake-gui(1)` offers interactive selection of a generator
-when creating a new build tree.
+on certain platforms. The :manual:`cmake(1)` command-line tool
+:option:`--help <cmake --help>` output lists available generators on the
+current platform. Use its :option:`-G <cmake -G>` option to specify the
+generator for a new build tree. The :manual:`cmake-gui(1)` offers
+interactive selection of a generator when creating a new build tree.
CMake Generators
================
@@ -108,9 +108,9 @@ Extra Generators
================
Some of the `CMake Generators`_ listed in the :manual:`cmake(1)`
-command-line tool ``--help`` output may have variants that specify
-an extra generator for an auxiliary IDE tool. Such generator
-names have the form ``<extra-generator> - <main-generator>``.
+command-line tool :option:`--help <cmake --help>` output may have
+variants that specify an extra generator for an auxiliary IDE tool.
+Such generator names have the form ``<extra-generator> - <main-generator>``.
The following extra generators are known to CMake.
.. toctree::
diff --git a/Help/manual/cmake-gui.1.rst b/Help/manual/cmake-gui.1.rst
index 281986f1b..dd0eecab3 100644
--- a/Help/manual/cmake-gui.1.rst
+++ b/Help/manual/cmake-gui.1.rst
@@ -9,7 +9,7 @@ Synopsis
.. parsed-literal::
cmake-gui [<options>]
- cmake-gui [<options>] {<path-to-source> | <path-to-existing-build>}
+ cmake-gui [<options>] <path-to-source | path-to-existing-build>
cmake-gui [<options>] -S <path-to-source> -B <path-to-build>
cmake-gui [<options>] --browse-manual
@@ -29,19 +29,25 @@ native tool on their platform.
Options
=======
-``-S <path-to-source>``
+.. program:: cmake-gui
+
+.. option:: -S <path-to-source>
+
Path to root directory of the CMake project to build.
-``-B <path-to-build>``
+.. option:: -B <path-to-build>
+
Path to directory which CMake will use as the root of build directory.
If the directory doesn't already exist CMake will make it.
-``--preset=<preset-name>``
+.. option:: --preset=<preset-name>
+
Name of the preset to use from the project's
:manual:`presets <cmake-presets(7)>` files, if it has them.
-``--browse-manual``
+.. option:: --browse-manual
+
Open the CMake reference manual in a browser and immediately exit.
.. include:: OPTIONS_HELP.txt
diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst
index 16917ffd6..0bd561f42 100644
--- a/Help/manual/cmake-language.7.rst
+++ b/Help/manual/cmake-language.7.rst
@@ -74,7 +74,7 @@ encoded in UTF-8 on Windows (using UTF-16 to call system APIs).
Furthermore, CMake 3.0 and above allow a leading UTF-8
`Byte-Order Mark`_ in source files.
-.. _`Byte-Order Mark`: http://en.wikipedia.org/wiki/Byte_order_mark
+.. _Byte-Order Mark: https://en.wikipedia.org/wiki/Byte_order_mark
Source Files
------------
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 93beea9f8..d161a284f 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -193,6 +193,7 @@ They are normally called through the :command:`find_package` command.
/module/FindOpenGL
/module/FindOpenMP
/module/FindOpenSceneGraph
+ /module/FindOpenSP
/module/FindOpenSSL
/module/FindOpenThreads
/module/Findosg
@@ -236,6 +237,7 @@ They are normally called through the :command:`find_package` command.
/module/FindRuby
/module/FindSDL
/module/FindSDL_image
+ /module/FindSDL_gfx
/module/FindSDL_mixer
/module/FindSDL_net
/module/FindSDL_sound
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index f6ab0c7fb..d6a30ffd0 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -52,6 +52,16 @@ to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.25
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0142: The Xcode generator does not append per-config suffixes to library search paths. </policy/CMP0142>
+ CMP0141: MSVC debug information format flags are selected by an abstraction. </policy/CMP0141>
+ CMP0140: The return() command checks its arguments. </policy/CMP0140>
+
Policies Introduced by CMake 3.24
=================================
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index a96c704a5..da699d86a 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -10,6 +10,8 @@ cmake-presets(7)
Introduction
============
+.. versionadded:: 3.19
+
One problem that CMake users often face is sharing settings with other people
for common ways to configure a project. This may be done to support CI builds,
or for users who frequently use the same build. CMake supports two main files,
@@ -19,10 +21,10 @@ supports files included with the ``include`` field.
``CMakePresets.json`` and ``CMakeUserPresets.json`` live in the project's root
directory. They both have exactly the same format, and both are optional
-(though at least one must be present if ``--preset`` is specified).
-``CMakePresets.json`` is meant to specify project-wide build details, while
-``CMakeUserPresets.json`` is meant for developers to specify their own local
-build details.
+(though at least one must be present if :option:`--preset <cmake --preset>`
+is specified). ``CMakePresets.json`` is meant to specify project-wide build
+details, while ``CMakeUserPresets.json`` is meant for developers to specify
+their own local build details.
``CMakePresets.json`` may be checked into a version control system, and
``CMakeUserPresets.json`` should NOT be checked in. For example, if a
@@ -40,7 +42,6 @@ The files are a JSON document with an object as the root:
The root object recognizes the following fields:
``version``
-
A required integer representing the version of the JSON schema.
The supported versions are:
@@ -59,32 +60,29 @@ The root object recognizes the following fields:
``5``
.. versionadded:: 3.24
-``cmakeMinimumRequired``
+ ``6``
+ .. versionadded:: 3.25
+``cmakeMinimumRequired``
An optional object representing the minimum version of CMake needed to
build this project. This object consists of the following fields:
``major``
-
An optional integer representing the major version.
``minor``
-
An optional integer representing the minor version.
``patch``
-
An optional integer representing the patch version.
``include``
-
An optional array of strings representing files to include. If the filenames
are not absolute, they are considered relative to the current file.
This is allowed in preset files specifying version ``4`` or above.
See `Includes`_ for discussion of the constraints on included files.
``vendor``
-
An optional map containing vendor-specific information. CMake does not
interpret the contents of this field except to verify that it is a map if
it does exist. However, the keys should be a vendor-specific domain name
@@ -93,20 +91,25 @@ The root object recognizes the following fields:
desired by the vendor, though will typically be a map.
``configurePresets``
-
An optional array of `Configure Preset`_ objects.
This is allowed in preset files specifying version ``1`` or above.
``buildPresets``
-
An optional array of `Build Preset`_ objects.
This is allowed in preset files specifying version ``2`` or above.
``testPresets``
-
An optional array of `Test Preset`_ objects.
This is allowed in preset files specifying version ``2`` or above.
+``packagePresets``
+ An optional array of `Package Preset`_ objects.
+ This is allowed in preset files specifying version ``6`` or above.
+
+``workflowPresets``
+ An optional array of `Workflow Preset`_ objects.
+ This is allowed in preset files specifying version ``6`` or above.
+
Includes
^^^^^^^^
@@ -134,15 +137,14 @@ Each entry of the ``configurePresets`` array is a JSON object
that may contain the following fields:
``name``
-
A required string representing the machine-friendly name of the preset.
This identifier is used in the :ref:`cmake --preset <CMake Options>` option.
There must not be two configure presets in the union of ``CMakePresets.json``
and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a configure preset may have the same name as a build or test preset.
+ However, a configure preset may have the same name as a build, test,
+ package, or workflow preset.
``hidden``
-
An optional boolean specifying whether or not a preset should be hidden.
If a preset is hidden, it cannot be used in the ``--preset=`` argument,
will not show up in the :manual:`CMake GUI <cmake-gui(1)>`, and does not
@@ -151,7 +153,6 @@ that may contain the following fields:
other presets to inherit via the ``inherits`` field.
``inherits``
-
An optional array of strings representing the names of presets to inherit
from. This field can also be a string, which is equivalent to an array
containing one string.
@@ -160,7 +161,7 @@ that may contain the following fields:
presets by default (except ``name``, ``hidden``, ``inherits``,
``description``, and ``displayName``), but can override them as
desired. If multiple ``inherits`` presets provide conflicting values for
- the same field, the earlier preset in the ``inherits`` list will be
+ the same field, the earlier preset in the ``inherits`` array will be
preferred.
A preset can only inherit from another preset that is defined in the
@@ -169,12 +170,10 @@ that may contain the following fields:
``CMakeUserPresets.json``.
``condition``
-
An optional `Condition`_ object. This is allowed in preset files specifying
version ``3`` or above.
``vendor``
-
An optional map containing vendor-specific information. CMake does not
interpret the contents of this field except to verify that it is a map
if it does exist. However, it should follow the same conventions as the
@@ -183,47 +182,43 @@ that may contain the following fields:
when appropriate.
``displayName``
-
An optional string with a human-friendly name of the preset.
``description``
-
An optional string with a human-friendly description of the preset.
``generator``
-
An optional string representing the generator to use for the preset. If
``generator`` is not specified, it must be inherited from the
``inherits`` preset (unless this preset is ``hidden``). In version ``3``
or above, this field may be omitted to fall back to regular generator
discovery procedure.
- Note that for Visual Studio generators, unlike in the command line ``-G``
- argument, you cannot include the platform name in the generator name. Use
- the ``architecture`` field instead.
+ Note that for Visual Studio generators, unlike in the command line
+ :option:`-G <cmake -G>` argument, you cannot include the platform name
+ in the generator name. Use the ``architecture`` field instead.
``architecture``, ``toolset``
-
Optional fields representing the platform and toolset, respectively, for
- generators that support them. Each may be either a string or an object
- with the following fields:
+ :manual:`generators <cmake-generators(7)>` that support them.
- ``value``
+ See :option:`cmake -A` option for possible values for ``architecture``
+ and :option:`cmake -T` for ``toolset``.
+
+ Each may be either a string or an object with the following fields:
+ ``value``
An optional string representing the value.
``strategy``
-
An optional string telling CMake how to handle the ``architecture`` or
``toolset`` field. Valid values are:
``"set"``
-
Set the respective value. This will result in an error for generators
that do not support the respective field.
``"external"``
-
Do not set the value, even if the generator supports it. This is
useful if, for example, a preset uses the Ninja generator, and an IDE
knows how to set up the Visual C++ environment from the
@@ -231,8 +226,10 @@ that may contain the following fields:
ignore the field, but the IDE can use them to set up the environment
before invoking CMake.
-``toolchainFile``
+ If no ``strategy`` field is given, or if the field uses the string form
+ rather than the object form, the behavior is the same as ``"set"``.
+``toolchainFile``
An optional string representing the path to the toolchain file.
This field supports `macro expansion`_. If a relative path is specified,
it is calculated relative to the build directory, and if not found,
@@ -241,7 +238,6 @@ that may contain the following fields:
specifying version ``3`` or above.
``binaryDir``
-
An optional string representing the path to the output binary directory.
This field supports `macro expansion`_. If a relative path is specified,
it is calculated relative to the source directory. If ``binaryDir`` is not
@@ -250,20 +246,17 @@ that may contain the following fields:
omitted.
``installDir``
-
An optional string representing the path to the installation directory.
This field supports `macro expansion`_. If a relative path is specified,
it is calculated relative to the source directory. This is allowed in
preset files specifying version ``3`` or above.
``cmakeExecutable``
-
An optional string representing the path to the CMake executable to use
for this preset. This is reserved for use by IDEs, and is not used by
CMake itself. IDEs that use this field should expand any macros in it.
``cacheVariables``
-
An optional map of cache variables. The key is the variable name (which
may not be an empty string), and the value is either ``null``, a boolean
(which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type
@@ -271,11 +264,9 @@ that may contain the following fields:
supports `macro expansion`_), or an object with the following fields:
``type``
-
An optional string representing the type of the variable.
``value``
-
A required string or boolean representing the value of the variable.
A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field
supports `macro expansion`_.
@@ -288,7 +279,6 @@ that may contain the following fields:
a value was inherited from another preset.
``environment``
-
An optional map of environment variables. The key is the variable name
(which may not be an empty string), and the value is either ``null`` or
a string representing the value of the variable. Each variable is set
@@ -306,73 +296,68 @@ that may contain the following fields:
a value was inherited from another preset.
``warnings``
-
An optional object specifying the warnings to enable. The object may
contain the following fields:
``dev``
-
- An optional boolean. Equivalent to passing ``-Wdev`` or ``-Wno-dev``
- on the command line. This may not be set to ``false`` if ``errors.dev``
- is set to ``true``.
+ An optional boolean. Equivalent to passing :option:`-Wdev <cmake -Wdev>`
+ or :option:`-Wno-dev <cmake -Wno-dev>` on the command line. This may not
+ be set to ``false`` if ``errors.dev`` is set to ``true``.
``deprecated``
-
- An optional boolean. Equivalent to passing ``-Wdeprecated`` or
- ``-Wno-deprecated`` on the command line. This may not be set to
- ``false`` if ``errors.deprecated`` is set to ``true``.
+ An optional boolean. Equivalent to passing
+ :option:`-Wdeprecated <cmake -Wdeprecated>` or
+ :option:`-Wno-deprecated <cmake -Wno-deprecated>` on the command line.
+ This may not be set to ``false`` if ``errors.deprecated`` is set to
+ ``true``.
``uninitialized``
-
An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--warn-uninitialized`` on the command line.
+ :option:`--warn-uninitialized <cmake --warn-uninitialized>` on the command
+ line.
``unusedCli``
-
An optional boolean. Setting this to ``false`` is equivalent to passing
- ``--no-warn-unused-cli`` on the command line.
+ :option:`--no-warn-unused-cli <cmake --no-warn-unused-cli>` on the command
+ line.
``systemVars``
-
An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--check-system-vars`` on the command line.
+ :option:`--check-system-vars <cmake --check-system-vars>` on the command
+ line.
``errors``
-
An optional object specifying the errors to enable. The object may
contain the following fields:
``dev``
-
- An optional boolean. Equivalent to passing ``-Werror=dev`` or
- ``-Wno-error=dev`` on the command line. This may not be set to ``true``
- if ``warnings.dev`` is set to ``false``.
+ An optional boolean. Equivalent to passing :option:`-Werror=dev <cmake -Werror>`
+ or :option:`-Wno-error=dev <cmake -Werror>` on the command line.
+ This may not be set to ``true`` if ``warnings.dev`` is set to ``false``.
``deprecated``
-
- An optional boolean. Equivalent to passing ``-Werror=deprecated`` or
- ``-Wno-error=deprecated`` on the command line. This may not be set to
- ``true`` if ``warnings.deprecated`` is set to ``false``.
+ An optional boolean. Equivalent to passing
+ :option:`-Werror=deprecated <cmake -Werror>` or
+ :option:`-Wno-error=deprecated <cmake -Werror>` on the command line.
+ This may not be set to ``true`` if ``warnings.deprecated`` is set to
+ ``false``.
``debug``
-
An optional object specifying debug options. The object may contain the
following fields:
``output``
-
An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-output`` on the command line.
+ :option:`--debug-output <cmake --debug-output>` on the command line.
``tryCompile``
-
An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-trycompile`` on the command line.
+ :option:`--debug-trycompile <cmake --debug-trycompile>` on the command
+ line.
``find``
-
An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-find`` on the command line.
+ :option:`--debug-find <cmake --debug-find>` on the command line.
Build Preset
^^^^^^^^^^^^
@@ -381,24 +366,23 @@ Each entry of the ``buildPresets`` array is a JSON object
that may contain the following fields:
``name``
-
A required string representing the machine-friendly name of the preset.
This identifier is used in the
:ref:`cmake --build --preset <Build Tool Mode>` option.
There must not be two build presets in the union of ``CMakePresets.json``
and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a build preset may have the same name as a configure or test preset.
+ However, a build preset may have the same name as a configure, test,
+ package, or workflow preset.
``hidden``
-
An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the ``--preset`` argument
+ If a preset is hidden, it cannot be used in the
+ :option:`--preset <cmake --preset>` argument
and does not have to have a valid ``configurePreset``, even from
inheritance. ``hidden`` presets are intended to be used as a base for
other presets to inherit via the ``inherits`` field.
``inherits``
-
An optional array of strings representing the names of presets to inherit
from. This field can also be a string, which is equivalent to an array
containing one string.
@@ -407,7 +391,7 @@ that may contain the following fields:
``inherits`` presets by default (except ``name``, ``hidden``,
``inherits``, ``description``, and ``displayName``), but can override
them as desired. If multiple ``inherits`` presets provide conflicting
- values for the same field, the earlier preset in the ``inherits`` list
+ values for the same field, the earlier preset in the ``inherits`` array
will be preferred.
A preset can only inherit from another preset that is defined in the
@@ -416,12 +400,10 @@ that may contain the following fields:
``CMakeUserPresets.json``.
``condition``
-
An optional `Condition`_ object. This is allowed in preset files specifying
version ``3`` or above.
``vendor``
-
An optional map containing vendor-specific information. CMake does not
interpret the contents of this field except to verify that it is a map
if it does exist. However, it should follow the same conventions as the
@@ -430,15 +412,12 @@ that may contain the following fields:
when appropriate.
``displayName``
-
An optional string with a human-friendly name of the preset.
``description``
-
An optional string with a human-friendly description of the preset.
``environment``
-
An optional map of environment variables. The key is the variable name
(which may not be an empty string), and the value is either ``null`` or
a string representing the value of the variable. Each variable is set
@@ -469,7 +448,6 @@ that may contain the following fields:
project.
``configurePreset``
-
An optional string specifying the name of a configure preset to
associate with this build preset. If ``configurePreset`` is not
specified, it must be inherited from the inherits preset (unless this
@@ -478,36 +456,30 @@ that may contain the following fields:
configuration did.
``inheritConfigureEnvironment``
-
An optional boolean that defaults to true. If true, the environment
variables from the associated configure preset are inherited after all
inherited build preset environments, but before environment variables
explicitly specified in this build preset.
``jobs``
-
- An optional integer. Equivalent to passing ``--parallel`` or ``-j`` on
- the command line.
+ An optional integer. Equivalent to passing
+ :option:`--parallel <cmake--build --parallel>` or ``-j`` on the command line.
``targets``
-
An optional string or array of strings. Equivalent to passing
- ``--target`` or ``-t`` on the command line. Vendors may ignore the
- targets property or hide build presets that explicitly specify targets.
- This field supports macro expansion.
+ :option:`--target <cmake--build --target>` or ``-t`` on the command line.
+ Vendors may ignore the targets property or hide build presets that
+ explicitly specify targets. This field supports macro expansion.
``configuration``
-
- An optional string. Equivalent to passing ``--config`` on the command
- line.
+ An optional string. Equivalent to passing
+ :option:`--config <cmake--build --config>` on the command line.
``cleanFirst``
-
- An optional bool. If true, equivalent to passing ``--clean-first`` on
- the command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--clean-first <cmake--build --clean-first>` on the command line.
``resolvePackageReferences``
-
An optional string that specifies the package resolve mode. This is
allowed in preset files specifying version ``4`` or above.
@@ -517,24 +489,23 @@ that may contain the following fields:
package references, this option does nothing. Valid values are:
``on``
-
Causes package references to be resolved before attempting a build.
``off``
-
Package references will not be resolved. Note that this may cause
errors in some build environments, such as .NET SDK style projects.
``only``
-
Only resolve package references, but do not perform a build.
.. note::
- The command line parameter ``--resolve-package-references`` will take
- priority over this setting. If the command line parameter is not provided
- and this setting is not specified, an environment-specific cache variable
- will be evaluated to decide, if package restoration should be performed.
+ The command line parameter
+ :option:`--resolve-package-references <cmake--build --resolve-package-references>`
+ will take priority over this setting. If the command line parameter is not
+ provided and this setting is not specified, an environment-specific cache
+ variable will be evaluated to decide, if package restoration should be
+ performed.
When using the Visual Studio generator, package references are defined
using the :prop_tgt:`VS_PACKAGE_REFERENCES` property. Package references
@@ -543,12 +514,10 @@ that may contain the following fields:
done from within a configure preset.
``verbose``
-
- An optional bool. If true, equivalent to passing ``--verbose`` on the
- command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--verbose <cmake--build --verbose>` on the command line.
``nativeToolOptions``
-
An optional array of strings. Equivalent to passing options after ``--``
on the command line. The array values support macro expansion.
@@ -559,23 +528,22 @@ Each entry of the ``testPresets`` array is a JSON object
that may contain the following fields:
``name``
-
A required string representing the machine-friendly name of the preset.
- This identifier is used in the :ref:`ctest --preset <CTest Options>` option.
+ This identifier is used in the :option:`ctest --preset` option.
There must not be two test presets in the union of ``CMakePresets.json``
and ``CMakeUserPresets.json`` in the same directory with the same name.
- However, a test preset may have the same name as a configure or build preset.
+ However, a test preset may have the same name as a configure, build,
+ package, or workflow preset.
``hidden``
-
An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the ``--preset`` argument
+ If a preset is hidden, it cannot be used in the
+ :option:`--preset <ctest --preset>` argument
and does not have to have a valid ``configurePreset``, even from
inheritance. ``hidden`` presets are intended to be used as a base for
other presets to inherit via the ``inherits`` field.
``inherits``
-
An optional array of strings representing the names of presets to inherit
from. This field can also be a string, which is equivalent to an array
containing one string.
@@ -584,7 +552,7 @@ that may contain the following fields:
``inherits`` presets by default (except ``name``, ``hidden``,
``inherits``, ``description``, and ``displayName``), but can override
them as desired. If multiple ``inherits`` presets provide conflicting
- values for the same field, the earlier preset in the ``inherits`` list
+ values for the same field, the earlier preset in the ``inherits`` array
will be preferred.
A preset can only inherit from another preset that is defined in the
@@ -593,12 +561,10 @@ that may contain the following fields:
``CMakeUserPresets.json``.
``condition``
-
An optional `Condition`_ object. This is allowed in preset files specifying
version ``3`` or above.
``vendor``
-
An optional map containing vendor-specific information. CMake does not
interpret the contents of this field except to verify that it is a map
if it does exist. However, it should follow the same conventions as the
@@ -607,15 +573,12 @@ that may contain the following fields:
when appropriate.
``displayName``
-
An optional string with a human-friendly name of the preset.
``description``
-
An optional string with a human-friendly description of the preset.
``environment``
-
An optional map of environment variables. The key is the variable name
(which may not be an empty string), and the value is either ``null`` or
a string representing the value of the variable. Each variable is set
@@ -633,7 +596,6 @@ that may contain the following fields:
even if a value was inherited from another preset.
``configurePreset``
-
An optional string specifying the name of a configure preset to
associate with this test preset. If ``configurePreset`` is not
specified, it must be inherited from the inherits preset (unless this
@@ -642,233 +604,210 @@ that may contain the following fields:
configuration did and build did.
``inheritConfigureEnvironment``
-
An optional boolean that defaults to true. If true, the environment
variables from the associated configure preset are inherited after all
inherited test preset environments, but before environment variables
explicitly specified in this test preset.
``configuration``
-
- An optional string. Equivalent to passing ``--build-config`` on the
- command line.
+ An optional string. Equivalent to passing
+ :option:`--build-config <ctest --build-config>` on the command line.
``overwriteConfigurationFile``
-
An optional array of configuration options to overwrite options
specified in the CTest configuration file. Equivalent to passing
- ``--overwrite`` for each value in the array. The array values
- support macro expansion.
+ :option:`--overwrite <ctest --overwrite>` for each value in the array.
+ The array values support macro expansion.
``output``
-
An optional object specifying output options. The object may contain the
following fields.
``shortProgress``
-
- An optional bool. If true, equivalent to passing ``--progress`` on the
- command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--progress <ctest --progress>` on the command line.
``verbosity``
-
An optional string specifying verbosity level. Must be one of the
following:
``default``
-
Equivalent to passing no verbosity flags on the command line.
``verbose``
-
- Equivalent to passing ``--verbose`` on the command line.
+ Equivalent to passing :option:`--verbose <ctest --verbose>` on
+ the command line.
``extra``
-
- Equivalent to passing ``--extra-verbose`` on the command line.
+ Equivalent to passing :option:`--extra-verbose <ctest --extra-verbose>`
+ on the command line.
``debug``
-
- An optional bool. If true, equivalent to passing ``--debug`` on the
- command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--debug <ctest --debug>` on the command line.
``outputOnFailure``
-
An optional bool. If true, equivalent to passing
- ``--output-on-failure`` on the command line.
+ :option:`--output-on-failure <ctest --output-on-failure>` on the command
+ line.
``quiet``
-
- An optional bool. If true, equivalent to passing ``--quiet`` on the
- command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--quiet <ctest --quiet>` on the command line.
``outputLogFile``
-
An optional string specifying a path to a log file. Equivalent to
- passing ``--output-log`` on the command line. This field supports
- macro expansion.
+ passing :option:`--output-log <ctest --output-log>` on the command line.
+ This field supports macro expansion.
- ``labelSummary``
+ ``outputJUnitFile``
+ An optional string specifying a path to a JUnit file. Equivalent to
+ passing :option:`--output-junit <ctest --output-junit>` on the command line.
+ This field supports macro expansion. This is allowed in preset files
+ specifying version ``6`` or above.
+ ``labelSummary``
An optional bool. If false, equivalent to passing
- ``--no-label-summary`` on the command line.
+ :option:`--no-label-summary <ctest --no-label-summary>` on the command
+ line.
``subprojectSummary``
-
An optional bool. If false, equivalent to passing
- ``--no-subproject-summary`` on the command line.
+ :option:`--no-subproject-summary <ctest --no-subproject-summary>`
+ on the command line.
``maxPassedTestOutputSize``
-
An optional integer specifying the maximum output for passed tests in
- bytes. Equivalent to passing ``--test-output-size-passed`` on the
- command line.
+ bytes. Equivalent to passing
+ :option:`--test-output-size-passed <ctest --test-output-size-passed>`
+ on the command line.
``maxFailedTestOutputSize``
-
An optional integer specifying the maximum output for failed tests in
- bytes. Equivalent to passing ``--test-output-size-failed`` on the
- command line.
+ bytes. Equivalent to passing
+ :option:`--test-output-size-failed <ctest --test-output-size-failed>`
+ on the command line.
``testOutputTruncation``
-
An optional string specifying the test output truncation mode. Equivalent
- to passing ``--test-output-truncation`` on the command line."
- This is allowed in preset files specifying version ``5`` or above.
+ to passing
+ :option:`--test-output-truncation <ctest --test-output-truncation>` on
+ the command line. This is allowed in preset files specifying version
+ ``5`` or above.
``maxTestNameWidth``
-
An optional integer specifying the maximum width of a test name to
- output. Equivalent to passing ``--max-width`` on the command line.
+ output. Equivalent to passing :option:`--max-width <ctest --max-width>`
+ on the command line.
``filter``
-
An optional object specifying how to filter the tests to run. The object
may contain the following fields.
``include``
-
An optional object specifying which tests to include. The object may
contain the following fields.
``name``
-
An optional string specifying a regex for test names. Equivalent to
- passing ``--tests-regex`` on the command line. This field supports
- macro expansion. CMake regex syntax is described under
- :ref:`string(REGEX) <Regex Specification>`.
-
+ passing :option:`--tests-regex <ctest --tests-regex>` on the command
+ line. This field supports macro expansion. CMake regex syntax is
+ described under :ref:`string(REGEX) <Regex Specification>`.
``label``
-
An optional string specifying a regex for test labels. Equivalent to
- passing ``--label-regex`` on the command line. This field supports
- macro expansion.
+ passing :option:`--label-regex <ctest --label-regex>` on the command
+ line. This field supports macro expansion.
``useUnion``
-
- An optional bool. Equivalent to passing ``--union`` on the command
- line.
+ An optional bool. Equivalent to passing :option:`--union <ctest --union>`
+ on the command line.
``index``
-
An optional object specifying tests to include by test index. The
object may contain the following fields. Can also be an optional
string specifying a file with the command line syntax for
- ``--tests-information``. If specified as a string, this field
- supports macro expansion.
+ :option:`--tests-information <ctest --tests-information>`.
+ If specified as a string, this field supports macro expansion.
``start``
-
An optional integer specifying a test index to start testing at.
``end``
-
An optional integer specifying a test index to stop testing at.
``stride``
-
An optional integer specifying the increment.
``specificTests``
-
An optional array of integers specifying specific test indices to
run.
``exclude``
-
An optional object specifying which tests to exclude. The object may
contain the following fields.
``name``
-
An optional string specifying a regex for test names. Equivalent to
- passing ``--exclude-regex`` on the command line. This field supports
- macro expansion.
+ passing :option:`--exclude-regex <ctest --exclude-regex>` on the
+ command line. This field supports macro expansion.
``label``
-
An optional string specifying a regex for test labels. Equivalent to
- passing ``--label-exclude`` on the command line. This field supports
- macro expansion.
+ passing :option:`--label-exclude <ctest --label-exclude>` on the
+ command line. This field supports macro expansion.
``fixtures``
-
An optional object specifying which fixtures to exclude from adding
tests. The object may contain the following fields.
``any``
-
An optional string specifying a regex for text fixtures to exclude
- from adding any tests. Equivalent to ``--fixture-exclude-any`` on
+ from adding any tests. Equivalent to
+ :option:`--fixture-exclude-any <ctest --fixture-exclude-any>` on
the command line. This field supports macro expansion.
``setup``
-
An optional string specifying a regex for text fixtures to exclude
- from adding setup tests. Equivalent to ``--fixture-exclude-setup``
+ from adding setup tests. Equivalent to
+ :option:`--fixture-exclude-setup <ctest --fixture-exclude-setup>`
on the command line. This field supports macro expansion.
``cleanup``
-
An optional string specifying a regex for text fixtures to exclude
from adding cleanup tests. Equivalent to
- ``--fixture-exclude-cleanup`` on the command line. This field
- supports macro expansion.
+ :option:`--fixture-exclude-cleanup <ctest --fixture-exclude-cleanup>`
+ on the command line. This field supports macro expansion.
``execution``
-
An optional object specifying options for test execution. The object may
contain the following fields.
``stopOnFailure``
-
- An optional bool. If true, equivalent to passing ``--stop-on-failure``
- on the command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--stop-on-failure <ctest --stop-on-failure>` on the command
+ line.
``enableFailover``
-
- An optional bool. If true, equivalent to passing ``-F`` on the command
- line.
+ An optional bool. If true, equivalent to passing :option:`-F <ctest -F>`
+ on the command line.
``jobs``
-
- An optional integer. Equivalent to passing ``--parallel`` on the
- command line.
+ An optional integer. Equivalent to passing
+ :option:`--parallel <ctest --parallel>` on the command line.
``resourceSpecFile``
-
- An optional string. Equivalent to passing ``--resource-spec-file`` on
+ An optional string. Equivalent to passing
+ :option:`--resource-spec-file <ctest --resource-spec-file>` on
the command line. This field supports macro expansion.
``testLoad``
-
- An optional integer. Equivalent to passing ``--test-load`` on the
- command line.
+ An optional integer. Equivalent to passing
+ :option:`--test-load <ctest --test-load>` on the command line.
``showOnly``
-
- An optional string. Equivalent to passing ``--show-only`` on the
+ An optional string. Equivalent to passing
+ :option:`--show-only <ctest --show-only>` on the
command line. The string must be one of the following values:
``human``
@@ -876,13 +815,11 @@ that may contain the following fields:
``json-v1``
``repeat``
-
An optional object specifying how to repeat tests. Equivalent to
- passing ``--repeat`` on the command line. The object must have the
- following fields.
+ passing :option:`--repeat <ctest --repeat>` on the command line.
+ The object must have the following fields.
``mode``
-
A required string. Must be one of the following values:
``until-fail``
@@ -892,42 +829,204 @@ that may contain the following fields:
``after-timeout``
``count``
-
A required integer.
``interactiveDebugging``
-
An optional bool. If true, equivalent to passing
- ``--interactive-debug-mode 1`` on the command line. If false,
- equivalent to passing ``--interactive-debug-mode 0`` on the command
- line.
+ :option:`--interactive-debug-mode 1 <ctest --interactive-debug-mode>`
+ on the command line. If false, equivalent to passing
+ :option:`--interactive-debug-mode 0 <ctest --interactive-debug-mode>`
+ on the command line.
``scheduleRandom``
-
- An optional bool. If true, equivalent to passing ``--schedule-random``
- on the command line.
+ An optional bool. If true, equivalent to passing
+ :option:`--schedule-random <ctest --schedule-random>` on the command
+ line.
``timeout``
-
- An optional integer. Equivalent to passing ``--timeout`` on the
- command line.
+ An optional integer. Equivalent to passing
+ :option:`--timeout <ctest --timeout>` on the command line.
``noTestsAction``
-
An optional string specifying the behavior if no tests are found. Must
be one of the following values:
``default``
-
Equivalent to not passing any value on the command line.
``error``
-
- Equivalent to passing ``--no-tests=error`` on the command line.
+ Equivalent to passing :option:`--no-tests=error <ctest --no-tests>`
+ on the command line.
``ignore``
+ Equivalent to passing :option:`--no-tests=ignore <ctest --no-tests>`
+ on the command line.
+
+Package Preset
+^^^^^^^^^^^^^^
+
+Package presets may be used in schema version ``6`` or above. Each entry of
+the ``packagePresets`` array is a JSON object that may contain the following
+fields:
+
+``name``
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the :option:`cpack --preset` option.
+ There must not be two package presets in the union of ``CMakePresets.json``
+ and ``CMakeUserPresets.json`` in the same directory with the same name.
+ However, a package preset may have the same name as a configure, build,
+ test, or workflow preset.
+
+``hidden``
+ An optional boolean specifying whether or not a preset should be hidden.
+ If a preset is hidden, it cannot be used in the
+ :option:`--preset <cpack --preset>` argument
+ and does not have to have a valid ``configurePreset``, even from
+ inheritance. ``hidden`` presets are intended to be used as a base for
+ other presets to inherit via the ``inherits`` field.
+
+``inherits``
+ An optional array of strings representing the names of presets to inherit
+ from. This field can also be a string, which is equivalent to an array
+ containing one string.
+
+ The preset will inherit all of the fields from the
+ ``inherits`` presets by default (except ``name``, ``hidden``,
+ ``inherits``, ``description``, and ``displayName``), but can override
+ them as desired. If multiple ``inherits`` presets provide conflicting
+ values for the same field, the earlier preset in the ``inherits`` array
+ will be preferred.
+
+ A preset can only inherit from another preset that is defined in the
+ same file or in one of the files it includes (directly or indirectly).
+ Presets in ``CMakePresets.json`` may not inherit from presets in
+ ``CMakeUserPresets.json``.
+
+``condition``
+ An optional `Condition`_ object.
+
+``vendor``
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map
+ if it does exist. However, it should follow the same conventions as the
+ root-level ``vendor`` field. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
- Equivalent to passing ``--no-tests=ignore`` on the command line.
+``description``
+ An optional string with a human-friendly description of the preset.
+
+``environment``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or
+ a string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment. This field supports macro expansion, and environment
+ variables in this map may reference each other, and may be listed in any
+ order, as long as such references do not cause a cycle (for example, if
+ ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment``
+ and the ``environment`` from all its parents. If multiple presets in
+ this union define the same variable, the standard rules of ``inherits``
+ are applied. Setting a variable to ``null`` causes it to not be set,
+ even if a value was inherited from another preset.
+
+``configurePreset``
+ An optional string specifying the name of a configure preset to
+ associate with this package preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless this
+ preset is hidden). The build directory is inferred from the configure
+ preset, so packaging will run in the same ``binaryDir`` that the
+ configuration did and build did.
+
+``inheritConfigureEnvironment``
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after all
+ inherited package preset environments, but before environment variables
+ explicitly specified in this package preset.
+
+``generators``
+ An optional array of strings representing generators for CPack to use.
+
+``configurations``
+ An optional array of strings representing build configurations for CPack to
+ package.
+
+``variables``
+ An optional map of variables to pass to CPack, equivalent to
+ :option:`-D <cpack -D>` arguments. Each key is the name of a variable, and
+ the value is the string to assign to that variable.
+
+``configFile``
+ An optional string representing the config file for CPack to use.
+
+``output``
+ An optional object specifying output options. Valid keys are:
+
+ ``debug``
+ An optional boolean specifying whether or not to print debug information.
+ A value of ``true`` is equivalent to passing
+ :option:`--debug <cpack --debug>` on the command line.
+
+ ``verbose``
+ An optional boolean specifying whether or not to print verbosely. A value
+ of ``true`` is equivalent to passing :option:`--verbose <cpack --verbose>`
+ on the command line.
+
+``packageName``
+ An optional string representing the package name.
+
+``packageVersion``
+ An optional string representing the package version.
+
+``packageDirectory``
+ An optional string representing the directory in which to place the package.
+
+``vendorName``
+ An optional string representing the vendor name.
+
+.. _`Workflow Preset`:
+
+Workflow Preset
+^^^^^^^^^^^^^^^
+
+Workflow presets may be used in schema version ``6`` or above. Each entry of
+the ``workflowPresets`` array is a JSON object that may contain the following
+fields:
+
+``name``
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the
+ :ref:`cmake --workflow --preset <Workflow Mode>` option. There must not be
+ two workflow presets in the union of ``CMakePresets.json`` and
+ ``CMakeUserPresets.json`` in the same directory with the same name. However,
+ a workflow preset may have the same name as a configure, build, test, or
+ package preset.
+
+``displayName``
+ An optional string with a human-friendly name of the preset.
+
+``description``
+ An optional string with a human-friendly description of the preset.
+
+``steps``
+ A required array of objects describing the steps of the workflow. The first
+ step must be a configure preset, and all subsequent steps must be non-
+ configure presets whose ``configurePreset`` field matches the starting
+ configure preset. Each object may contain the following fields:
+
+ ``type``
+ A required string. The first step must be ``configure``. Subsequent steps
+ must be either ``build``, ``test``, or ``package``.
+
+ ``name``
+ A required string representing the name of the configure, build, test, or
+ package preset to run as this workflow step.
Condition
^^^^^^^^^
@@ -943,65 +1042,53 @@ a ``not``, ``anyOf``, or ``allOf`` condition) may not be ``null``. If it is an
object, it has the following fields:
``type``
-
A required string with one of the following values:
``"const"``
-
Indicates that the condition is constant. This is equivalent to using a
boolean in place of the object. The condition object will have the
following additional fields:
``value``
-
A required boolean which provides a constant value for the condition's
evaluation.
``"equals"``
``"notEquals"``
-
Indicates that the condition compares two strings to see if they are equal
(or not equal). The condition object will have the following additional
fields:
``lhs``
-
First string to compare. This field supports macro expansion.
``rhs``
-
Second string to compare. This field supports macro expansion.
``"inList"``
``"notInList"``
-
Indicates that the condition searches for a string in a list of strings.
The condition object will have the following additional fields:
``string``
-
A required string to search for. This field supports macro expansion.
``list``
-
- A required list of strings to search. This field supports macro
+ A required array of strings to search. This field supports macro
expansion, and uses short-circuit evaluation.
``"matches"``
``"notMatches"``
-
Indicates that the condition searches for a regular expression in a string.
The condition object will have the following additional fields:
``string``
-
A required string to search. This field supports macro expansion.
``regex``
-
A required regular expression to search for. This field supports macro
expansion.
@@ -1013,17 +1100,14 @@ object, it has the following fields:
conditions. The condition object will have the following additional fields:
``conditions``
-
A required array of condition objects. These conditions use short-circuit
evaluation.
``"not"``
-
Indicates that the condition is an inversion of another condition. The
condition object will have the following additional fields:
``condition``
-
A required condition object.
Macro Expansion
@@ -1045,46 +1129,37 @@ interpreted as a literal dollar sign.
Recognized macros include:
``${sourceDir}``
-
Path to the project source directory (i.e. the same as
:variable:`CMAKE_SOURCE_DIR`).
``${sourceParentDir}``
-
Path to the project source directory's parent directory.
``${sourceDirName}``
-
The last filename component of ``${sourceDir}``. For example, if
``${sourceDir}`` is ``/path/to/source``, this would be ``source``.
``${presetName}``
-
Name specified in the preset's ``name`` field.
``${generator}``
-
Generator specified in the preset's ``generator`` field. For build and
test presets, this will evaluate to the generator specified by
``configurePreset``.
``${hostSystemName}``
-
The name of the host operating system. Contains the same value as
:variable:`CMAKE_HOST_SYSTEM_NAME`. This is allowed in preset files
specifying version ``3`` or above.
``${fileDir}``
-
Path to the directory containing the preset file which contains the macro.
This is allowed in preset files specifying version ``4`` or above.
``${dollar}``
-
A literal dollar sign (``$``).
``${pathListSep}``
-
Native character for separating lists of paths, such as ``:`` or ``;``.
For example, by setting ``PATH`` to
@@ -1095,7 +1170,6 @@ Recognized macros include:
This is allowed in preset files specifying version ``5`` or above.
``$env{<variable-name>}``
-
Environment variable with name ``<variable-name>``. The variable name may
not be an empty string. If the variable is defined in the ``environment``
field, that value is used instead of the value from the parent environment.
@@ -1108,7 +1182,6 @@ Recognized macros include:
the casing of environment variable names consistent.
``$penv{<variable-name>}``
-
Similar to ``$env{<variable-name>}``, except that the value only comes from
the parent environment, and never from the ``environment`` field. This
allows you to prepend or append values to existing environment variables.
@@ -1118,7 +1191,6 @@ Recognized macros include:
references.
``$vendor{<macro-name>}``
-
An extension point for vendors to insert their own macros. CMake will not
be able to use presets which have a ``$vendor{<macro-name>}`` macro, and
effectively ignores such presets. However, it will still be able to use
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index d88322c6d..b17be8239 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -90,6 +90,7 @@ Properties on Directories
/prop_dir/RULE_LAUNCH_LINK
/prop_dir/SOURCE_DIR
/prop_dir/SUBDIRECTORIES
+ /prop_dir/SYSTEM
/prop_dir/TESTS
/prop_dir/TEST_INCLUDE_FILES
/prop_dir/VARIABLES
@@ -184,6 +185,16 @@ Properties on Targets
/prop_tgt/CUDA_STANDARD
/prop_tgt/CUDA_STANDARD_REQUIRED
/prop_tgt/CXX_EXTENSIONS
+ /prop_tgt/CXX_MODULE_DIRS
+ /prop_tgt/CXX_MODULE_DIRS_NAME
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SET
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SETS
+ /prop_tgt/CXX_MODULE_SET
+ /prop_tgt/CXX_MODULE_SET_NAME
+ /prop_tgt/CXX_MODULE_SETS
/prop_tgt/CXX_STANDARD
/prop_tgt/CXX_STANDARD_REQUIRED
/prop_tgt/DEBUG_POSTFIX
@@ -202,6 +213,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXPORT_COMPILE_COMMANDS
/prop_tgt/EXPORT_NAME
+ /prop_tgt/EXPORT_NO_SYSTEM
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES
@@ -262,6 +274,8 @@ Properties on Targets
/prop_tgt/INTERFACE_COMPILE_DEFINITIONS
/prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS
+ /prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS
+ /prop_tgt/INTERFACE_CXX_MODULE_SETS
/prop_tgt/INTERFACE_HEADER_SETS
/prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
@@ -327,6 +341,7 @@ Properties on Targets
/prop_tgt/MACOSX_RPATH
/prop_tgt/MANUALLY_ADDED_DEPENDENCIES
/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG
+ /prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT
/prop_tgt/MSVC_RUNTIME_LIBRARY
/prop_tgt/NAME
/prop_tgt/NO_SONAME
@@ -342,8 +357,8 @@ Properties on Targets
/prop_tgt/OSX_ARCHITECTURES_CONFIG
/prop_tgt/OUTPUT_NAME
/prop_tgt/OUTPUT_NAME_CONFIG
- /prop_tgt/PCH_WARN_INVALID
/prop_tgt/PCH_INSTANTIATE_TEMPLATES
+ /prop_tgt/PCH_WARN_INVALID
/prop_tgt/PDB_NAME
/prop_tgt/PDB_NAME_CONFIG
/prop_tgt/PDB_OUTPUT_DIRECTORY
@@ -375,6 +390,7 @@ Properties on Targets
/prop_tgt/Swift_LANGUAGE_VERSION
/prop_tgt/Swift_MODULE_DIRECTORY
/prop_tgt/Swift_MODULE_NAME
+ /prop_tgt/SYSTEM
/prop_tgt/TYPE
/prop_tgt/UNITY_BUILD
/prop_tgt/UNITY_BUILD_BATCH_SIZE
@@ -444,13 +460,17 @@ Properties on Targets
/prop_tgt/XCODE_SCHEME_ARGUMENTS
/prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT
/prop_tgt/XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
- /prop_tgt/XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
/prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
/prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
/prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ /prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ /prop_tgt/XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ /prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
/prop_tgt/XCODE_SCHEME_ENVIRONMENT
/prop_tgt/XCODE_SCHEME_EXECUTABLE
/prop_tgt/XCODE_SCHEME_GUARD_MALLOC
+ /prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION
+ /prop_tgt/XCODE_SCHEME_LAUNCH_MODE
/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES
/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index f156f9587..d0d6ea023 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -14,7 +14,7 @@ CMake can find and use Qt 4 and Qt 5 libraries. The Qt 4 libraries are found
by the :module:`FindQt4` find-module shipped with CMake, whereas the
Qt 5 libraries are found using "Config-file Packages" shipped with Qt 5. See
:manual:`cmake-packages(7)` for more information about CMake packages, and
-see `the Qt cmake manual <http://qt-project.org/doc/qt-5/cmake-manual.html>`_
+see `the Qt cmake manual <https://contribute.qt-project.org/doc/qt-5/cmake-manual.html>`_
for your Qt version.
Qt 4 and Qt 5 may be used together in the same
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index e194df078..8a8380714 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -17,6 +17,9 @@ determines the toolchain for host builds based on system introspection and
defaults. In cross-compiling scenarios, a toolchain file may be specified
with information about compiler and utility paths.
+.. versionadded:: 3.19
+ One may use :manual:`cmake-presets(7)` to specify toolchain files.
+
Languages
=========
@@ -58,20 +61,24 @@ Variables and Properties
========================
Several variables relate to the language components of a toolchain which are
-enabled. :variable:`CMAKE_<LANG>_COMPILER` is the full path to the compiler used
-for ``<LANG>``. :variable:`CMAKE_<LANG>_COMPILER_ID` is the identifier used
-by CMake for the compiler and :variable:`CMAKE_<LANG>_COMPILER_VERSION` is the
-version of the compiler.
-
-The :variable:`CMAKE_<LANG>_FLAGS` variables and the configuration-specific
-equivalents contain flags that will be added to the compile command when
-compiling a file of a particular language.
-
-As the linker is invoked by the compiler driver, CMake needs a way to determine
-which compiler to use to invoke the linker. This is calculated by the
-:prop_sf:`LANGUAGE` of source files in the target, and in the case of static
-libraries, the language of the dependent libraries. The choice CMake makes may
-be overridden with the :prop_tgt:`LINKER_LANGUAGE` target property.
+enabled:
+
+:variable:`CMAKE_<LANG>_COMPILER`
+ The full path to the compiler used for ``<LANG>``
+:variable:`CMAKE_<LANG>_COMPILER_ID`
+ The compiler identifier used by CMake
+:variable:`CMAKE_<LANG>_COMPILER_VERSION`
+ The version of the compiler.
+:variable:`CMAKE_<LANG>_FLAGS`
+ The variables and the configuration-specific equivalents contain flags that
+ will be added to the compile command when compiling a file of a particular
+ language.
+
+CMake needs a way to determine which compiler to use to invoke the linker.
+This is determined by the :prop_sf:`LANGUAGE` property of source files of the
+:manual:`target <cmake-buildsystem(7)>`, and in the case of static libraries,
+the ``LANGUAGE`` of the dependent libraries. The choice CMake makes may be overridden
+with the :prop_tgt:`LINKER_LANGUAGE` target property.
Toolchain Features
==================
@@ -96,7 +103,8 @@ Cross Compiling
===============
If :manual:`cmake(1)` is invoked with the command line parameter
-``--toolchain path/to/file`` or ``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, the
+:option:`--toolchain path/to/file <cmake --toolchain>` or
+:option:`-DCMAKE_TOOLCHAIN_FILE=path/to/file <cmake -D>`, the
file will be loaded early to set values for the compilers.
The :variable:`CMAKE_CROSSCOMPILING` variable is set to true when CMake is
cross-compiling.
@@ -132,24 +140,24 @@ as:
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
-The :variable:`CMAKE_SYSTEM_NAME` is the CMake-identifier of the target platform
-to build for.
-
-The :variable:`CMAKE_SYSTEM_PROCESSOR` is the CMake-identifier of the target architecture
-to build for.
+Where:
-The :variable:`CMAKE_SYSROOT` is optional, and may be specified if a sysroot
-is available.
-
-The :variable:`CMAKE_STAGING_PREFIX` is also optional. It may be used to specify
-a path on the host to install to. The :variable:`CMAKE_INSTALL_PREFIX` is always
-the runtime installation location, even when cross-compiling.
-
-The :variable:`CMAKE_<LANG>_COMPILER` variables may be set to full paths, or to
-names of compilers to search for in standard locations. For toolchains that
-do not support linking binaries without custom flags or scripts one may set
-the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to ``STATIC_LIBRARY``
-to tell CMake not to try to link executables during its checks.
+:variable:`CMAKE_SYSTEM_NAME`
+ is the CMake-identifier of the target platform to build for.
+:variable:`CMAKE_SYSTEM_PROCESSOR`
+ is the CMake-identifier of the target architecture.
+:variable:`CMAKE_SYSROOT`
+ is optional, and may be specified if a sysroot is available.
+:variable:`CMAKE_STAGING_PREFIX`
+ is also optional. It may be used to specify a path on the host to install to.
+ The :variable:`CMAKE_INSTALL_PREFIX` is always the runtime installation
+ location, even when cross-compiling.
+:variable:`CMAKE_<LANG>_COMPILER`
+ variable may be set to full paths, or to names of compilers to search for
+ in standard locations. For toolchains that do not support linking binaries
+ without custom flags or scripts one may set the
+ :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to ``STATIC_LIBRARY`` to
+ tell CMake not to try to link executables during its checks.
CMake ``find_*`` commands will look in the sysroot, and the :variable:`CMAKE_FIND_ROOT_PATH`
entries by default in all cases, as well as looking in the host system root prefix.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 7c8a7fac7..cd46615ec 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -128,9 +128,9 @@ Variables that Provide Information
/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
/variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
- /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION
/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
+ /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
/variable/CMAKE_XCODE_BUILD_SYSTEM
@@ -207,9 +207,9 @@ Variables that Change Behavior
/variable/CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
/variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
- /variable/CMAKE_FIND_USE_INSTALL_PREFIX
/variable/CMAKE_FIND_USE_CMAKE_PATH
/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
+ /variable/CMAKE_FIND_USE_INSTALL_PREFIX
/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY
/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH
/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
@@ -228,12 +228,12 @@ Variables that Change Behavior
/variable/CMAKE_LIBRARY_PATH
/variable/CMAKE_LINK_DIRECTORIES_BEFORE
/variable/CMAKE_LINK_LIBRARIES_ONLY_TARGETS
- /variable/CMAKE_MFC_FLAG
/variable/CMAKE_MAXIMUM_RECURSION_DEPTH
/variable/CMAKE_MESSAGE_CONTEXT
/variable/CMAKE_MESSAGE_CONTEXT_SHOW
/variable/CMAKE_MESSAGE_INDENT
/variable/CMAKE_MESSAGE_LOG_LEVEL
+ /variable/CMAKE_MFC_FLAG
/variable/CMAKE_MODULE_PATH
/variable/CMAKE_POLICY_DEFAULT_CMPNNNN
/variable/CMAKE_POLICY_WARNING_CMPNNNN
@@ -272,12 +272,16 @@ Variables that Change Behavior
/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
/variable/CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
- /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
/variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
/variable/CMAKE_XCODE_SCHEME_ENVIRONMENT
/variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ /variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION
+ /variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE
/variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
/variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
/variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
@@ -300,10 +304,13 @@ Variables that Describe the System
/variable/ANDROID
/variable/APPLE
/variable/BORLAND
+ /variable/BSD
/variable/CMAKE_ANDROID_NDK_VERSION
/variable/CMAKE_CL_64
/variable/CMAKE_COMPILER_2005
/variable/CMAKE_HOST_APPLE
+ /variable/CMAKE_HOST_BSD
+ /variable/CMAKE_HOST_LINUX
/variable/CMAKE_HOST_SOLARIS
/variable/CMAKE_HOST_SYSTEM
/variable/CMAKE_HOST_SYSTEM_NAME
@@ -321,6 +328,7 @@ Variables that Describe the System
/variable/CYGWIN
/variable/GHSMULTI
/variable/IOS
+ /variable/LINUX
/variable/MINGW
/variable/MSVC
/variable/MSVC10
@@ -412,19 +420,19 @@ Variables that Control the Build
/variable/CMAKE_DEBUG_POSTFIX
/variable/CMAKE_DEFAULT_BUILD_TYPE
/variable/CMAKE_DEFAULT_CONFIGS
- /variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
/variable/CMAKE_DEPENDS_USE_COMPILER
+ /variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
/variable/CMAKE_ENABLE_EXPORTS
/variable/CMAKE_EXE_LINKER_FLAGS
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT
/variable/CMAKE_EXE_LINKER_FLAGS_INIT
/variable/CMAKE_FOLDER
- /variable/CMAKE_FRAMEWORK
- /variable/CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG
/variable/CMAKE_Fortran_FORMAT
/variable/CMAKE_Fortran_MODULE_DIRECTORY
/variable/CMAKE_Fortran_PREPROCESS
+ /variable/CMAKE_FRAMEWORK
+ /variable/CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG
/variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE
/variable/CMAKE_GLOBAL_AUTOGEN_TARGET
/variable/CMAKE_GLOBAL_AUTOGEN_TARGET_NAME
@@ -445,14 +453,14 @@ Variables that Control the Build
/variable/CMAKE_LANG_CPPCHECK
/variable/CMAKE_LANG_CPPLINT
/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE
- /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE
- /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED
- /variable/CMAKE_LANG_LINKER_LAUNCHER
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED
/variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LANG_LINK_LIBRARY_FLAG
+ /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE
+ /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED
/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG
+ /variable/CMAKE_LANG_LINKER_LAUNCHER
/variable/CMAKE_LANG_VISIBILITY_PRESET
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG
@@ -475,8 +483,9 @@ Variables that Control the Build
/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG
/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT
/variable/CMAKE_MODULE_LINKER_FLAGS_INIT
- /variable/CMAKE_MSVCIDE_RUN_PATH
+ /variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
/variable/CMAKE_MSVC_RUNTIME_LIBRARY
+ /variable/CMAKE_MSVCIDE_RUN_PATH
/variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX
/variable/CMAKE_NO_BUILTIN_CHRPATH
/variable/CMAKE_NO_SYSTEM_FROM_IMPORTED
@@ -484,8 +493,8 @@ Variables that Control the Build
/variable/CMAKE_OSX_ARCHITECTURES
/variable/CMAKE_OSX_DEPLOYMENT_TARGET
/variable/CMAKE_OSX_SYSROOT
- /variable/CMAKE_PCH_WARN_INVALID
/variable/CMAKE_PCH_INSTANTIATE_TEMPLATES
+ /variable/CMAKE_PCH_WARN_INVALID
/variable/CMAKE_PDB_OUTPUT_DIRECTORY
/variable/CMAKE_PDB_OUTPUT_DIRECTORY_CONFIG
/variable/CMAKE_PLATFORM_NO_VERSIONED_SONAME
@@ -502,6 +511,7 @@ Variables that Control the Build
/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG
/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG_INIT
/variable/CMAKE_STATIC_LINKER_FLAGS_INIT
+ /variable/CMAKE_TASKING_TOOLSET
/variable/CMAKE_TRY_COMPILE_CONFIGURATION
/variable/CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES
/variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
@@ -538,6 +548,10 @@ Variables for Languages
.. toctree::
:maxdepth: 1
+ /variable/CMAKE_C_COMPILE_FEATURES
+ /variable/CMAKE_C_EXTENSIONS
+ /variable/CMAKE_C_STANDARD
+ /variable/CMAKE_C_STANDARD_REQUIRED
/variable/CMAKE_COMPILER_IS_GNUCC
/variable/CMAKE_COMPILER_IS_GNUCXX
/variable/CMAKE_COMPILER_IS_GNUG77
@@ -552,10 +566,6 @@ Variables for Languages
/variable/CMAKE_CXX_EXTENSIONS
/variable/CMAKE_CXX_STANDARD
/variable/CMAKE_CXX_STANDARD_REQUIRED
- /variable/CMAKE_C_COMPILE_FEATURES
- /variable/CMAKE_C_EXTENSIONS
- /variable/CMAKE_C_STANDARD
- /variable/CMAKE_C_STANDARD_REQUIRED
/variable/CMAKE_Fortran_MODDIR_DEFAULT
/variable/CMAKE_Fortran_MODDIR_FLAG
/variable/CMAKE_Fortran_MODOUT_FLAG
@@ -573,6 +583,7 @@ Variables for Languages
/variable/CMAKE_LANG_ARCHIVE_CREATE
/variable/CMAKE_LANG_ARCHIVE_FINISH
/variable/CMAKE_LANG_BYTE_ORDER
+ /variable/CMAKE_LANG_COMPILE_OBJECT
/variable/CMAKE_LANG_COMPILER
/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN
/variable/CMAKE_LANG_COMPILER_ID
@@ -580,7 +591,6 @@ Variables for Languages
/variable/CMAKE_LANG_COMPILER_PREDEFINES_COMMAND
/variable/CMAKE_LANG_COMPILER_TARGET
/variable/CMAKE_LANG_COMPILER_VERSION
- /variable/CMAKE_LANG_COMPILE_OBJECT
/variable/CMAKE_LANG_CREATE_SHARED_LIBRARY
/variable/CMAKE_LANG_CREATE_SHARED_MODULE
/variable/CMAKE_LANG_CREATE_STATIC_LIBRARY
@@ -653,12 +663,12 @@ Variables for CTest
/variable/CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS
/variable/CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS
/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE
- /variable/CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION
/variable/CTEST_CUSTOM_MEMCHECK_IGNORE
/variable/CTEST_CUSTOM_POST_MEMCHECK
/variable/CTEST_CUSTOM_POST_TEST
/variable/CTEST_CUSTOM_PRE_MEMCHECK
/variable/CTEST_CUSTOM_PRE_TEST
+ /variable/CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION
/variable/CTEST_CUSTOM_TESTS_IGNORE
/variable/CTEST_CUSTOM_WARNING_EXCEPTION
/variable/CTEST_CUSTOM_WARNING_MATCH
@@ -694,9 +704,9 @@ Variables for CTest
/variable/CTEST_SCP_COMMAND
/variable/CTEST_SCRIPT_DIRECTORY
/variable/CTEST_SITE
+ /variable/CTEST_SOURCE_DIRECTORY
/variable/CTEST_SUBMIT_INACTIVITY_TIMEOUT
/variable/CTEST_SUBMIT_URL
- /variable/CTEST_SOURCE_DIRECTORY
/variable/CTEST_SVN_COMMAND
/variable/CTEST_SVN_OPTIONS
/variable/CTEST_SVN_UPDATE_OPTIONS
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 38105dd28..b31ad118a 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -9,8 +9,7 @@ Synopsis
.. parsed-literal::
`Generate a Project Buildsystem`_
- cmake [<options>] <path-to-source>
- cmake [<options>] <path-to-existing-build>
+ cmake [<options>] <path-to-source | path-to-existing-build>
cmake [<options>] -S <path-to-source> -B <path-to-build>
`Build a Project`_
@@ -23,7 +22,7 @@ Synopsis
cmake --open <dir>
`Run a Script`_
- cmake [{-D <var>=<value>}...] -P <cmake-script-file>
+ cmake [-D <var>=<value>]... -P <cmake-script-file>
`Run a Command-Line Tool`_
cmake -E <command> [<options>]
@@ -31,6 +30,9 @@ Synopsis
`Run the Find-Package Tool`_
cmake --find-package [<options>]
+ `Run a Workflow Preset`_
+ cmake --workflow [<options>]
+
`View Help`_
cmake --help[-<topic>]
@@ -96,9 +98,10 @@ Build Tree
Generator
This chooses the kind of buildsystem to generate. See the
:manual:`cmake-generators(7)` manual for documentation of all generators.
- Run ``cmake --help`` to see a list of generators available locally.
- Optionally use the ``-G`` option below to specify a generator, or simply
- accept the default CMake chooses for the current platform.
+ Run :option:`cmake --help` to see a list of generators available locally.
+ Optionally use the :option:`-G <cmake -G>` option below to specify a
+ generator, or simply accept the default CMake chooses for the current
+ platform.
When using one of the :ref:`Command-Line Build Tool Generators`
CMake expects that the environment needed by the compiler toolchain
@@ -139,6 +142,9 @@ source and build trees and generate a buildsystem:
$ cmake .
``cmake [<options>] -S <path-to-source> -B <path-to-build>``
+
+ .. versionadded:: 3.13
+
Uses ``<path-to-build>`` as the build tree and ``<path-to-source>``
as the source tree. The specified paths may be absolute or relative
to the current working directory. The source tree must contain a
@@ -152,11 +158,11 @@ source and build trees and generate a buildsystem:
In all cases the ``<options>`` may be zero or more of the `Options`_ below.
The above styles for specifying the source and build trees may be mixed.
-Paths specified with ``-S`` or ``-B`` are always classified as source or
-build trees, respectively. Paths specified with plain arguments are
-classified based on their content and the types of paths given earlier.
-If only one type of path is given, the current working directory (cwd)
-is used for the other. For example:
+Paths specified with :option:`-S <cmake -S>` or :option:`-B <cmake -B>`
+are always classified as source or build trees, respectively. Paths
+specified with plain arguments are classified based on their content
+and the types of paths given earlier. If only one type of path is given,
+the current working directory (cwd) is used for the other. For example:
============================== ============ ===========
Command Line Source Dir Build Dir
@@ -195,51 +201,60 @@ automatically choosing and invoking the appropriate native build tool.
Options
-------
+.. program:: cmake
+
.. include:: OPTIONS_BUILD.txt
-``--fresh``
+.. option:: --fresh
+
.. versionadded:: 3.24
Perform a fresh configuration of the build tree.
This removes any existing ``CMakeCache.txt`` file and associated
``CMakeFiles/`` directory, and recreates them from scratch.
-``-L[A][H]``
+.. option:: -L[A][H]
+
List non-advanced cached variables.
List ``CACHE`` variables will run CMake and list all the variables from
the CMake ``CACHE`` that are not marked as ``INTERNAL`` or :prop_cache:`ADVANCED`.
This will effectively display current CMake settings, which can then be
- changed with ``-D`` option. Changing some of the variables may result
- in more variables being created. If ``A`` is specified, then it will
- display also advanced variables. If ``H`` is specified, it will also
+ changed with :option:`-D <cmake -D>` option. Changing some of the variables
+ may result in more variables being created. If ``A`` is specified, then it
+ will display also advanced variables. If ``H`` is specified, it will also
display help for each variable.
-``-N``
+.. option:: -N
+
View mode only.
Only load the cache. Do not actually run configure and generate
steps.
-``--graphviz=[file]``
+.. option:: --graphviz=<file>
+
Generate graphviz of dependencies, see :module:`CMakeGraphVizOptions` for more.
Generate a graphviz input file that will contain all the library and
executable dependencies in the project. See the documentation for
:module:`CMakeGraphVizOptions` for more details.
-``--system-information [file]``
+.. option:: --system-information [file]
+
Dump information about this system.
Dump a wide range of information about the current system. If run
from the top of a binary tree for a CMake project it will dump
additional information such as the cache, log files etc.
-``--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>``
- Set the log level.
+.. option:: --log-level=<level>
+
+ Set the log ``<level>``.
The :command:`message` command will only output messages of the specified
- log level or higher. The default log level is ``STATUS``.
+ log level or higher. The valid log levels are ``ERROR``, ``WARNING``,
+ ``NOTICE``, ``STATUS`` (default), ``VERBOSE``, ``DEBUG``, or ``TRACE``.
To make a log level persist between CMake runs, set
:variable:`CMAKE_MESSAGE_LOG_LEVEL` as a cache variable instead.
@@ -249,7 +264,12 @@ Options
For backward compatibility reasons, ``--loglevel`` is also accepted as a
synonym for this option.
-``--log-context``
+ .. versionadded:: 3.25
+ See the :command:`cmake_language` command for a way to
+ :ref:`query the current message logging level <query_message_log_level>`.
+
+.. option:: --log-context
+
Enable the :command:`message` command outputting context attached to each
message.
@@ -259,24 +279,36 @@ Options
When this command line option is given, :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
is ignored.
-``--debug-trycompile``
- Do not delete the :command:`try_compile` build tree.
- Only useful on one :command:`try_compile` at a time.
+.. option:: --debug-trycompile
+
+ Do not delete the files and directories created for
+ :command:`try_compile` / :command:`try_run` calls.
+ This is useful in debugging failed checks.
+
+ Note that some uses of :command:`try_compile` may use the same build tree,
+ which will limit the usefulness of this option if a project executes more
+ than one :command:`try_compile`. For example, such uses may change results
+ as artifacts from a previous try-compile may cause a different test to either
+ pass or fail incorrectly. This option is best used only when debugging.
+
+ (With respect to the preceding, the :command:`try_run` command
+ is effectively a :command:`try_compile`. Any combination of the two
+ is subject to the potential issues described.)
- Do not delete the files and directories created for :command:`try_compile`
- calls. This is useful in debugging failed try_compiles. It may
- however change the results of the try-compiles as old junk from a
- previous try-compile may cause a different test to either pass or
- fail incorrectly. This option is best used for one try-compile at a
- time, and only when debugging.
+ .. versionadded:: 3.25
+
+ When this option is enabled, every try-compile check prints a log
+ message reporting the directory in which the check is performed.
+
+.. option:: --debug-output
-``--debug-output``
Put cmake in a debug mode.
Print extra information during the cmake run like stack traces with
:command:`message(SEND_ERROR)` calls.
-``--debug-find``
+.. option:: --debug-find
+
Put cmake find commands in a debug mode.
Print extra find call information during the cmake run to standard
@@ -284,32 +316,39 @@ Options
See also the :variable:`CMAKE_FIND_DEBUG_MODE` variable for debugging
a more local part of the project.
-``--debug-find-pkg=<pkg>[,...]``
+.. option:: --debug-find-pkg=<pkg>[,...]
+
Put cmake find commands in a debug mode when running under calls
to :command:`find_package(\<pkg\>) <find_package>`, where ``<pkg>``
is an entry in the given comma-separated list of case-sensitive package
names.
- Like ``--debug-find``, but limiting scope to the specified packages.
+ Like :option:`--debug-find <cmake --debug-find>`, but limiting scope
+ to the specified packages.
+
+.. option:: --debug-find-var=<var>[,...]
-``--debug-find-var=<var>[,...]``
Put cmake find commands in a debug mode when called with ``<var>``
as the result variable, where ``<var>`` is an entry in the given
comma-separated list.
- Like ``--debug-find``, but limiting scope to the specified variable names.
+ Like :option:`--debug-find <cmake --debug-find>`, but limiting scope
+ to the specified variable names.
+
+.. option:: --trace
-``--trace``
Put cmake in trace mode.
Print a trace of all calls made and from where.
-``--trace-expand``
+.. option:: --trace-expand
+
Put cmake in trace mode.
- Like ``--trace``, but with variables expanded.
+ Like :option:`--trace <cmake --trace>`, but with variables expanded.
+
+.. option:: --trace-format=<format>
-``--trace-format=<format>``
Put cmake in trace mode and sets the trace output format.
``<format>`` can be one of the following values.
@@ -395,46 +434,57 @@ Options
Indicates the version of the JSON format. The version has a
major and minor components following semantic version conventions.
-``--trace-source=<file>``
+.. option:: --trace-source=<file>
+
Put cmake in trace mode, but output only lines of a specified file.
Multiple options are allowed.
-``--trace-redirect=<file>``
+.. option:: --trace-redirect=<file>
+
Put cmake in trace mode and redirect trace output to a file instead of stderr.
-``--warn-uninitialized``
+.. option:: --warn-uninitialized
+
Warn about uninitialized values.
Print a warning when an uninitialized variable is used.
-``--warn-unused-vars``
+.. option:: --warn-unused-vars
+
Does nothing. In CMake versions 3.2 and below this enabled warnings about
unused variables. In CMake versions 3.3 through 3.18 the option was broken.
In CMake 3.19 and above the option has been removed.
-``--no-warn-unused-cli``
+.. option:: --no-warn-unused-cli
+
Don't warn about command line options.
Don't find variables that are declared on the command line, but not
used.
-``--check-system-vars``
+.. option:: --check-system-vars
+
Find problems with variable usage in system files.
Normally, unused and uninitialized variables are searched for only
in :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR`.
This flag tells CMake to warn about other files as well.
-``--compile-no-warning-as-error``
+.. option:: --compile-no-warning-as-error
+
Ignore target property :prop_tgt:`COMPILE_WARNING_AS_ERROR` and variable
:variable:`CMAKE_COMPILE_WARNING_AS_ERROR`, preventing warnings from being
treated as errors on compile.
-``--profiling-output=<path>``
- Used in conjunction with ``--profiling-format`` to output to a given path.
+.. option:: --profiling-output=<path>
+
+ Used in conjunction with
+ :option:`--profiling-format <cmake --profiling-format>` to output to a
+ given path.
+
+.. option:: --profiling-format=<file>
-``--profiling-format=<file>``
Enable the output of profiling data of CMake script in the given format.
This can aid performance analysis of CMake scripts executed. Third party
@@ -445,7 +495,8 @@ Options
about:tracing tab of Google Chrome or using a plugin for a tool like Trace
Compass.
-``--preset <preset>``, ``--preset=<preset>``
+.. option:: --preset <preset>, --preset=<preset>
+
Reads a :manual:`preset <cmake-presets(7)>` from
``<path-to-source>/CMakePresets.json`` and
``<path-to-source>/CMakeUserPresets.json``. The preset may specify the
@@ -461,15 +512,20 @@ Options
a variable called ``MYVAR`` to ``1``, but the user sets it to ``2`` with a
``-D`` argument, the value ``2`` is preferred.
-``--list-presets, --list-presets=<[configure | build | test | all]>``
- Lists the available presets. If no option is specified only configure presets
- will be listed. The current working directory must contain CMake preset files.
+.. option:: --list-presets[=<type>]
+
+ Lists the available presets of the specified ``<type>``. Valid values for
+ ``<type>`` are ``configure``, ``build``, ``test``, ``package``, or ``all``.
+ If ``<type>`` is omitted, ``configure`` is assumed. The current working
+ directory must contain CMake preset files.
.. _`Build Tool Mode`:
Build a Project
===============
+.. program:: cmake
+
CMake provides a command-line signature to build an already-generated
project binary tree:
@@ -481,21 +537,29 @@ project binary tree:
This abstracts a native build tool's command-line interface with the
following options:
-``--build <dir>``
+.. option:: --build <dir>
+
Project binary directory to be built. This is required (unless a preset
is specified) and must be first.
-``--preset <preset>``, ``--preset=<preset>``
+.. program:: cmake--build
+
+.. option:: --preset <preset>, --preset=<preset>
+
Use a build preset to specify build options. The project binary directory
is inferred from the ``configurePreset`` key. The current working directory
must contain CMake preset files.
See :manual:`preset <cmake-presets(7)>` for more details.
-``--list-presets``
+.. option:: --list-presets
+
Lists the available build presets. The current working directory must
contain CMake preset files.
-``--parallel [<jobs>], -j [<jobs>]``
+.. option:: -j [<jobs>], --parallel [<jobs>]
+
+ .. versionadded:: 3.12
+
The maximum number of concurrent processes to use when building.
If ``<jobs>`` is omitted the native build tool's default number is used.
@@ -505,24 +569,29 @@ following options:
Some native build tools always build in parallel. The use of ``<jobs>``
value of ``1`` can be used to limit to a single job.
-``--target <tgt>..., -t <tgt>...``
+.. option:: -t <tgt>..., --target <tgt>...
+
Build ``<tgt>`` instead of the default target. Multiple targets may be
given, separated by spaces.
-``--config <cfg>``
+.. option:: --config <cfg>
+
For multi-configuration tools, choose configuration ``<cfg>``.
-``--clean-first``
+.. option:: --clean-first
+
Build target ``clean`` first, then build.
- (To clean only, use ``--target clean``.)
+ (To clean only, use :option:`--target clean <cmake--build --target>`.)
+
+.. option:: --resolve-package-references=<value>
-``--resolve-package-references=<on|off|only>``
.. versionadded:: 3.23
Resolve remote package references from external package managers (e.g. NuGet)
- before build. When set to ``on`` (default), packages will be restored before
- building a target. When set to ``only``, the packages will be restored, but no
- build will be performed. When set to ``off``, no packages will be restored.
+ before build. When ``<value>`` is set to ``on`` (default), packages will be
+ restored before building a target. When ``<value>`` is set to ``only``, the
+ packages will be restored, but no build will be performed. When
+ ``<value>`` is set to ``off``, no packages will be restored.
If the target does not define any package references, this option does nothing.
@@ -539,10 +608,12 @@ following options:
are restored using NuGet. It can be disabled by setting the
``CMAKE_VS_NUGET_PACKAGE_RESTORE`` variable to ``OFF``.
-``--use-stderr``
+.. option:: --use-stderr
+
Ignored. Behavior is default in CMake >= 3.0.
-``--verbose, -v``
+.. option:: -v, --verbose
+
Enable verbose output - if supported - including the build commands to be
executed.
@@ -550,14 +621,17 @@ following options:
:variable:`CMAKE_VERBOSE_MAKEFILE` cached variable is set.
-``--``
+.. option:: --
+
Pass remaining options to the native tool.
-Run ``cmake --build`` with no options for quick help.
+Run :option:`cmake --build` with no options for quick help.
Install a Project
=================
+.. program:: cmake
+
CMake provides a command-line signature to install an already-generated
project binary tree:
@@ -569,34 +643,45 @@ This may be used after building a project to run installation without
using the generated build system or the native build tool.
The options are:
-``--install <dir>``
+.. option:: --install <dir>
+
Project binary directory to install. This is required and must be first.
-``--config <cfg>``
+.. program:: cmake--install
+
+.. option:: --config <cfg>
+
For multi-configuration generators, choose configuration ``<cfg>``.
-``--component <comp>``
+.. option:: --component <comp>
+
Component-based install. Only install component ``<comp>``.
-``--default-directory-permissions <permissions>``
+.. option:: --default-directory-permissions <permissions>
+
Default directory install permissions. Permissions in format ``<u=rwx,g=rx,o=rx>``.
-``--prefix <prefix>``
+.. option:: --prefix <prefix>
+
Override the installation prefix, :variable:`CMAKE_INSTALL_PREFIX`.
-``--strip``
+.. option:: --strip
+
Strip before installing.
-``-v, --verbose``
+.. option:: -v, --verbose
+
Enable verbose output.
This option can be omitted if :envvar:`VERBOSE` environment variable is set.
-Run ``cmake --install`` with no options for quick help.
+Run :option:`cmake --install` with no options for quick help.
Open a Project
==============
+.. program:: cmake
+
.. code-block:: shell
cmake --open <dir>
@@ -610,14 +695,26 @@ supported by some generators.
Run a Script
============
+.. program:: cmake
+
.. code-block:: shell
- cmake [{-D <var>=<value>}...] -P <cmake-script-file> [-- <unparsed-options>...]
+ cmake [-D <var>=<value>]... -P <cmake-script-file> [-- <unparsed-options>...]
+
+.. program:: cmake-P
+
+.. option:: -D <var>=<value>
+
+ Define a variable for script mode.
-Process the given cmake file as a script written in the CMake
-language. No configure or generate step is performed and the cache
-is not modified. If variables are defined using ``-D``, this must be
-done before the ``-P`` argument.
+.. program:: cmake
+
+.. option:: -P <cmake-script-file>
+
+ Process the given cmake file as a script written in the CMake
+ language. No configure or generate step is performed and the cache
+ is not modified. If variables are defined using ``-D``, this must be
+ done before the ``-P`` argument.
Any options after ``--`` are not parsed by CMake, but they are still included
in the set of :variable:`CMAKE_ARGV<n> <CMAKE_ARGV0>` variables passed to the
@@ -629,16 +726,24 @@ script (including the ``--`` itself).
Run a Command-Line Tool
=======================
+.. program:: cmake
+
CMake provides builtin command-line tools through the signature
.. code-block:: shell
cmake -E <command> [<options>]
-Run ``cmake -E`` or ``cmake -E help`` for a summary of commands.
+.. option:: -E [help]
+
+ Run ``cmake -E`` or ``cmake -E help`` for a summary of commands.
+
+.. program:: cmake-E
+
Available commands are:
-``capabilities``
+.. option:: capabilities
+
.. versionadded:: 3.7
Report cmake capabilities in JSON format. The output is a JSON object
@@ -648,7 +753,7 @@ Available commands are:
A JSON object with version information. Keys are:
``string``
- The full version string as displayed by cmake ``--version``.
+ The full version string as displayed by cmake :option:`--version <cmake --version>`.
``major``
The major version number in integer form.
``minor``
@@ -675,7 +780,8 @@ Available commands are:
Optional member that may be present when the generator supports
platform specification via :variable:`CMAKE_GENERATOR_PLATFORM`
- (``-A ...``). The value is a list of platforms known to be supported.
+ (:option:`-A ... <cmake -A>`). The value is a list of platforms known to
+ be supported.
``extraGenerators``
A list of strings with all the extra generators compatible with
the generator.
@@ -700,30 +806,52 @@ Available commands are:
``true`` if cmake supports server-mode and ``false`` otherwise.
Always false since CMake 3.20.
-``cat [--] <files>...``
+ ``tls``
+ .. versionadded:: 3.25
+
+ ``true`` if TLS support is enabled and ``false`` otherwise.
+
+.. option:: cat [--] <files>...
+
.. versionadded:: 3.18
Concatenate files and print on the standard output.
- .. versionadded:: 3.24
+ .. program:: cmake-E_cat
+
+ .. option:: --
+
+ .. versionadded:: 3.24
+
Added support for the double dash argument ``--``. This basic implementation
of ``cat`` does not support any options, so using a option starting with
``-`` will result in an error. Use ``--`` to indicate the end of options, in
case a file starts with ``-``.
-``chdir <dir> <cmd> [<arg>...]``
+.. program:: cmake-E
+
+.. option:: chdir <dir> <cmd> [<arg>...]
+
Change the current working directory and run a command.
-``compare_files [--ignore-eol] <file1> <file2>``
+.. option:: compare_files [--ignore-eol] <file1> <file2>
+
Check if ``<file1>`` is same as ``<file2>``. If files are the same,
then returns ``0``, if not it returns ``1``. In case of invalid
arguments, it returns 2.
- .. versionadded:: 3.14
- The ``--ignore-eol`` option implies line-wise comparison and ignores
- LF/CRLF differences.
+ .. program:: cmake-E_compare_files
+
+ .. option:: --ignore-eol
+
+ .. versionadded:: 3.14
+
+ The option implies line-wise comparison and ignores LF/CRLF differences.
+
+.. program:: cmake-E
+
+.. option:: copy <file>... <destination>
-``copy <file>... <destination>``
Copy files to ``<destination>`` (either file or directory).
If multiple files are specified, the ``<destination>`` must be
directory and it must exist. Wildcards are not supported.
@@ -733,7 +861,8 @@ Available commands are:
.. versionadded:: 3.5
Support for multiple input files.
-``copy_directory <dir>... <destination>``
+.. option:: copy_directory <dir>... <destination>
+
Copy content of ``<dir>...`` directories to ``<destination>`` directory.
If ``<destination>`` directory does not exist it will be created.
``copy_directory`` does follow symlinks.
@@ -745,7 +874,8 @@ Available commands are:
The command now fails when the source directory does not exist.
Previously it succeeded by creating an empty destination directory.
-``copy_if_different <file>... <destination>``
+.. option:: copy_if_different <file>... <destination>
+
Copy files to ``<destination>`` (either file or directory) if
they have changed.
If multiple files are specified, the ``<destination>`` must be
@@ -755,7 +885,8 @@ Available commands are:
.. versionadded:: 3.5
Support for multiple input files.
-``create_symlink <old> <new>``
+.. option:: create_symlink <old> <new>
+
Create a symbolic link ``<new>`` naming ``<old>``.
.. versionadded:: 3.13
@@ -764,7 +895,8 @@ Available commands are:
.. note::
Path to where ``<new>`` symbolic link will be created has to exist beforehand.
-``create_hardlink <old> <new>``
+.. option:: create_hardlink <old> <new>
+
.. versionadded:: 3.19
Create a hard link ``<new>`` naming ``<old>``.
@@ -773,31 +905,65 @@ Available commands are:
Path to where ``<new>`` hard link will be created has to exist beforehand.
``<old>`` has to exist beforehand.
-``echo [<string>...]``
+.. option:: echo [<string>...]
+
Displays arguments as text.
-``echo_append [<string>...]``
+.. option:: echo_append [<string>...]
+
Displays arguments as text but no new line.
-``env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]``
+.. option:: env [<options>] [--] <command> [<arg>...]
+
.. versionadded:: 3.1
- Run command in a modified environment.
+ Run command in a modified environment. Options are:
+
+ .. program:: cmake-E_env
+
+ .. option:: NAME=VALUE
+
+ Replaces the current value of ``NAME`` with ``VALUE``.
+
+ .. option:: --unset=NAME
+
+ Unsets the current value of ``NAME``.
+
+ .. option:: --modify ENVIRONMENT_MODIFICATION
+
+ .. versionadded:: 3.25
+
+ Apply a single :prop_test:`ENVIRONMENT_MODIFICATION` operation to the
+ modified environment.
+
+ The ``NAME=VALUE`` and ``--unset=NAME`` options are equivalent to
+ ``--modify NAME=set:VALUE`` and ``--modify NAME=unset:``, respectively.
+ Note that ``--modify NAME=reset:`` resets ``NAME`` to the value it had
+ when ``cmake`` launched (or unsets it), not to the most recent
+ ``NAME=VALUE`` option.
+
+ .. option:: --
+
+ .. versionadded:: 3.24
- .. versionadded:: 3.24
Added support for the double dash argument ``--``. Use ``--`` to stop
interpreting options/environment variables and treat the next argument as
the command, even if it start with ``-`` or contains a ``=``.
-``environment``
+.. program:: cmake-E
+
+.. option:: environment
+
Display the current environment variables.
-``false``
+.. option:: false
+
.. versionadded:: 3.16
Do nothing, with an exit code of 1.
-``make_directory <dir>...``
+.. option:: make_directory <dir>...
+
Create ``<dir>`` directories. If necessary, create parent
directories too. If a directory already exists it will be
silently ignored.
@@ -805,13 +971,15 @@ Available commands are:
.. versionadded:: 3.5
Support for multiple input directories.
-``md5sum <file>...``
+.. option:: md5sum <file>...
+
Create MD5 checksum of files in ``md5sum`` compatible format::
351abe79cd3800b38cdfb25d45015a15 file1.txt
052f86c15bbde68af55c7f7b340ab639 file2.txt
-``sha1sum <file>...``
+.. option:: sha1sum <file>...
+
.. versionadded:: 3.10
Create SHA1 checksum of files in ``sha1sum`` compatible format::
@@ -819,7 +987,8 @@ Available commands are:
4bb7932a29e6f73c97bb9272f2bdc393122f86e0 file1.txt
1df4c8f318665f9a5f2ed38f55adadb7ef9f559c file2.txt
-``sha224sum <file>...``
+.. option:: sha224sum <file>...
+
.. versionadded:: 3.10
Create SHA224 checksum of files in ``sha224sum`` compatible format::
@@ -827,7 +996,8 @@ Available commands are:
b9b9346bc8437bbda630b0b7ddfc5ea9ca157546dbbf4c613192f930 file1.txt
6dfbe55f4d2edc5fe5c9197bca51ceaaf824e48eba0cc453088aee24 file2.txt
-``sha256sum <file>...``
+.. option:: sha256sum <file>...
+
.. versionadded:: 3.10
Create SHA256 checksum of files in ``sha256sum`` compatible format::
@@ -835,7 +1005,8 @@ Available commands are:
76713b23615d31680afeb0e9efe94d47d3d4229191198bb46d7485f9cb191acc file1.txt
15b682ead6c12dedb1baf91231e1e89cfc7974b3787c1e2e01b986bffadae0ea file2.txt
-``sha384sum <file>...``
+.. option:: sha384sum <file>...
+
.. versionadded:: 3.10
Create SHA384 checksum of files in ``sha384sum`` compatible format::
@@ -843,7 +1014,8 @@ Available commands are:
acc049fedc091a22f5f2ce39a43b9057fd93c910e9afd76a6411a28a8f2b8a12c73d7129e292f94fc0329c309df49434 file1.txt
668ddeb108710d271ee21c0f3acbd6a7517e2b78f9181c6a2ff3b8943af92b0195dcb7cce48aa3e17893173c0a39e23d file2.txt
-``sha512sum <file>...``
+.. option:: sha512sum <file>...
+
.. versionadded:: 3.10
Create SHA512 checksum of files in ``sha512sum`` compatible format::
@@ -851,7 +1023,8 @@ Available commands are:
2a78d7a6c5328cfb1467c63beac8ff21794213901eaadafd48e7800289afbc08e5fb3e86aa31116c945ee3d7bf2a6194489ec6101051083d1108defc8e1dba89 file1.txt
7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d file2.txt
-``remove [-f] <file>...``
+.. option:: remove [-f] <file>...
+
.. deprecated:: 3.17
Remove the file(s). The planned behavior was that if any of the
@@ -864,7 +1037,8 @@ Available commands are:
The implementation was buggy and always returned 0. It cannot be fixed without
breaking backwards compatibility. Use ``rm`` instead.
-``remove_directory <dir>...``
+.. option:: remove_directory <dir>...
+
.. deprecated:: 3.17
Remove ``<dir>`` directories and their contents. If a directory does
@@ -877,11 +1051,13 @@ Available commands are:
.. versionadded:: 3.16
If ``<dir>`` is a symlink to a directory, just the symlink will be removed.
-``rename <oldname> <newname>``
+.. option:: rename <oldname> <newname>
+
Rename a file or directory (on one volume). If file with the ``<newname>`` name
already exists, then it will be silently replaced.
-``rm [-rRf] [--] <file|dir>...``
+.. option:: rm [-rRf] [--] <file|dir>...
+
.. versionadded:: 3.17
Remove the files ``<file>`` or directories ``<dir>``.
@@ -892,22 +1068,29 @@ Available commands are:
situations instead. Use ``--`` to stop interpreting options and treat all
remaining arguments as paths, even if they start with ``-``.
-``server``
+.. option:: server
+
Launch :manual:`cmake-server(7)` mode.
-``sleep <number>...``
+.. option:: sleep <number>...
+
.. versionadded:: 3.0
Sleep for given number of seconds.
-``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...]``
+.. option:: tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...]
+
Create or extract a tar or zip archive. Options are:
- ``c``
+ .. program:: cmake-E_tar
+
+ .. option:: c
+
Create a new archive containing the specified files.
If used, the ``<pathname>...`` argument is mandatory.
- ``x``
+ .. option:: x
+
Extract to disk from the archive.
.. versionadded:: 3.15
@@ -916,33 +1099,40 @@ Available commands are:
When extracting selected files or directories, you must provide their exact
names including the path, as printed by list (``-t``).
- ``t``
+ .. option:: t
+
List archive contents.
.. versionadded:: 3.15
The ``<pathname>...`` argument could be used to list only selected files
or directories.
- ``v``
+ .. option:: v
+
Produce verbose output.
- ``z``
+ .. option:: z
+
Compress the resulting archive with gzip.
- ``j``
+ .. option:: j
+
Compress the resulting archive with bzip2.
- ``J``
+ .. option:: J
+
.. versionadded:: 3.1
Compress the resulting archive with XZ.
- ``--zstd``
+ .. option:: --zstd
+
.. versionadded:: 3.15
Compress the resulting archive with Zstandard.
- ``--files-from=<file>``
+ .. option:: --files-from=<file>
+
.. versionadded:: 3.1
Read file names from the given file, one per line.
@@ -950,25 +1140,29 @@ Available commands are:
except for ``--add-file=<name>`` to add files whose
names start in ``-``.
- ``--format=<format>``
+ .. option:: --format=<format>
+
.. versionadded:: 3.3
Specify the format of the archive to be created.
Supported formats are: ``7zip``, ``gnutar``, ``pax``,
``paxr`` (restricted pax, default), and ``zip``.
- ``--mtime=<date>``
+ .. option:: --mtime=<date>
+
.. versionadded:: 3.1
Specify modification time recorded in tarball entries.
- ``--touch``
+ .. option:: --touch
+
.. versionadded:: 3.24
Use current local timestamp instead of extracting file timestamps
from the archive.
- ``--``
+ .. option:: --
+
.. versionadded:: 3.1
Stop interpreting options and treat all remaining arguments
@@ -983,7 +1177,10 @@ Available commands are:
``tar`` tool. The command now also parses all flags, and if an invalid flag
was provided, a warning is issued.
-``time <command> [<args>...]``
+.. program:: cmake-E
+
+.. option:: time <command> [<args>...]
+
Run command and display elapsed time.
.. versionadded:: 3.5
@@ -991,15 +1188,18 @@ Available commands are:
through to the child process. This may break scripts that worked around the
bug with their own extra quoting or escaping.
-``touch <file>...``
+.. option:: touch <file>...
+
Creates ``<file>`` if file do not exist.
If ``<file>`` exists, it is changing ``<file>`` access and modification times.
-``touch_nocreate <file>...``
+.. option:: touch_nocreate <file>...
+
Touch a file if it exists but do not create it. If a file does
not exist it will be silently ignored.
-``true``
+.. option:: true
+
.. versionadded:: 3.16
Do nothing, with an exit code of 0.
@@ -1009,28 +1209,34 @@ Windows-specific Command-Line Tools
The following ``cmake -E`` commands are available only on Windows:
-``delete_regv <key>``
+.. option:: delete_regv <key>
+
Delete Windows registry value.
-``env_vs8_wince <sdkname>``
+.. option:: env_vs8_wince <sdkname>
+
.. versionadded:: 3.2
Displays a batch file which sets the environment for the provided
Windows CE SDK installed in VS2005.
-``env_vs9_wince <sdkname>``
+.. option:: env_vs9_wince <sdkname>
+
.. versionadded:: 3.2
Displays a batch file which sets the environment for the provided
Windows CE SDK installed in VS2008.
-``write_regv <key> <value>``
+.. option:: write_regv <key> <value>
+
Write Windows registry value.
Run the Find-Package Tool
=========================
+.. program:: cmake--find-package
+
CMake provides a pkg-config like helper for Makefile-based projects:
.. code-block:: shell
@@ -1046,10 +1252,51 @@ autoconf-based projects (via ``share/aclocal/cmake.m4``).
This mode is not well-supported due to some technical limitations.
It is kept for compatibility but should not be used in new projects.
+.. _`Workflow Mode`:
+
+Run a Workflow Preset
+=====================
+
+.. program:: cmake
+
+:manual:`CMake Presets <cmake-presets(7)>` provides a way to execute multiple
+build steps in order:
+
+.. code-block:: shell
+
+ cmake --workflow [<options>]
+
+The options are:
+
+.. option:: --workflow
+
+ Select a :ref:`Workflow Preset` using one of the following options.
+
+.. program:: cmake--workflow
+
+.. option:: --preset <preset>, --preset=<preset>
+
+ Use a workflow preset to specify a workflow. The project binary directory
+ is inferred from the initial configure preset. The current working directory
+ must contain CMake preset files.
+ See :manual:`preset <cmake-presets(7)>` for more details.
+
+.. option:: --list-presets
+
+ Lists the available workflow presets. The current working directory must
+ contain CMake preset files.
+
+.. option:: --fresh
+
+ Perform a fresh configuration of the build tree.
+ This removes any existing ``CMakeCache.txt`` file and associated
+ ``CMakeFiles/`` directory, and recreates them from scratch.
View Help
=========
+.. program:: cmake
+
To print selected pages from the CMake documentation, use
.. code-block:: shell
diff --git a/Help/manual/cpack.1.rst b/Help/manual/cpack.1.rst
index 395cd4189..3f26d728e 100644
--- a/Help/manual/cpack.1.rst
+++ b/Help/manual/cpack.1.rst
@@ -26,12 +26,12 @@ All supported generators are specified in the :manual:`cpack-generators
<cpack-generators(7)>` manual. The command ``cpack --help`` prints a
list of generators supported for the target platform. Which of them are
to be used can be selected through the :variable:`CPACK_GENERATOR` variable
-or through the command-line option ``-G``.
+or through the command-line option :option:`-G <cpack -G>`.
The **cpack** program is steered by a configuration file written in the
:manual:`CMake language <cmake-language(7)>`. Unless chosen differently
-through the command-line option ``--config``, the file ``CPackConfig.cmake``
-in the current directory is used.
+through the command-line option :option:`--config <cpack --config>`, the
+file ``CPackConfig.cmake`` in the current directory is used.
In the standard CMake workflow, the file ``CPackConfig.cmake`` is generated
by the :manual:`cmake <cmake(1)>` executable, provided the :module:`CPack`
@@ -40,7 +40,10 @@ module is included by the project's ``CMakeLists.txt`` file.
Options
=======
-``-G <generators>``
+.. program:: cpack
+
+.. option:: -G <generators>
+
``<generators>`` is a :ref:`semicolon-separated list <CMake Language Lists>`
of generator names. ``cpack`` will iterate through this list and produce
package(s) in that generator's format according to the details provided in
@@ -48,7 +51,8 @@ Options
the :variable:`CPACK_GENERATOR` variable determines the default set of
generators that will be used.
-``-C <configs>``
+.. option:: -C <configs>
+
Specify the project configuration(s) to be packaged (e.g. ``Debug``,
``Release``, etc.), where ``<configs>`` is a
:ref:`semicolon-separated list <CMake Language Lists>`.
@@ -58,36 +62,44 @@ Options
The user is responsible for ensuring that the configuration(s) listed
have already been built before invoking ``cpack``.
-``-D <var>=<value>``
+.. option:: -D <var>=<value>
+
Set a CPack variable. This will override any value set for ``<var>`` in the
input file read by ``cpack``.
-``--config <configFile>``
+.. option:: --config <configFile>
+
Specify the configuration file read by ``cpack`` to provide the packaging
details. By default, ``CPackConfig.cmake`` in the current directory will
be used.
-``--verbose, -V``
+.. option:: -V, --verbose
+
Run ``cpack`` with verbose output. This can be used to show more details
from the package generation tools and is suitable for project developers.
-``--debug``
+.. option:: --debug
+
Run ``cpack`` with debug output. This option is intended mainly for the
developers of ``cpack`` itself and is not normally needed by project
developers.
-``--trace``
+.. option:: --trace
+
Put the underlying cmake scripts in trace mode.
-``--trace-expand``
+.. option:: --trace-expand
+
Put the underlying cmake scripts in expanded trace mode.
-``-P <packageName>``
+.. option:: -P <packageName>
+
Override/define the value of the :variable:`CPACK_PACKAGE_NAME` variable used
for packaging. Any value set for this variable in the ``CPackConfig.cmake``
file will then be ignored.
-``-R <packageVersion>``
+.. option:: -R <packageVersion>
+
Override/define the value of the :variable:`CPACK_PACKAGE_VERSION`
variable used for packaging. It will override a value set in the
``CPackConfig.cmake`` file or one automatically computed from
@@ -95,16 +107,26 @@ Options
:variable:`CPACK_PACKAGE_VERSION_MINOR` and
:variable:`CPACK_PACKAGE_VERSION_PATCH`.
-``-B <packageDirectory>``
+.. option:: -B <packageDirectory>
+
Override/define :variable:`CPACK_PACKAGE_DIRECTORY`, which controls the
directory where CPack will perform its packaging work. The resultant
package(s) will be created at this location by default and a
``_CPack_Packages`` subdirectory will also be created below this directory to
use as a working area during package creation.
-``--vendor <vendorName>``
+.. option:: --vendor <vendorName>
+
Override/define :variable:`CPACK_PACKAGE_VENDOR`.
+.. option:: --preset <presetName>
+
+ Use a preset from :manual:`cmake-presets(7)`.
+
+.. option:: --list-presets
+
+ List presets from :manual:`cmake-presets(7)`.
+
.. include:: OPTIONS_HELP.txt
See Also
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 06f0d4eaa..3497a9fc1 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -10,12 +10,24 @@ Synopsis
.. parsed-literal::
- ctest [<options>]
- ctest --build-and-test <path-to-source> <path-to-build>
- --build-generator <generator> [<options>...]
- [--build-options <opts>...] [--test-command <command> [<args>...]]
- ctest {-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>}
- [-- <dashboard-options>...]
+ `Run Tests`_
+ ctest [<options>]
+
+ `Build and Test Mode`_
+ ctest --build-and-test <path-to-source> <path-to-build>
+ --build-generator <generator> [<options>...]
+ [--build-options <opts>...]
+ [--test-command <command> [<args>...]]
+
+ `Dashboard Client`_
+ ctest -D <dashboard> [-- <dashboard-options>...]
+ ctest -M <model> -T <action> [-- <dashboard-options>...]
+ ctest -S <script> [-- <dashboard-options>...]
+ ctest -SP <script> [-- <dashboard-options>...]
+
+ `View Help`_
+ ctest --help[-<topic>]
+
Description
===========
@@ -25,22 +37,27 @@ CMake-generated build trees created for projects that use the
:command:`enable_testing` and :command:`add_test` commands have testing support.
This program will run the tests and report results.
-.. _`CTest Options`:
+.. _`Run Tests`:
-Options
-=======
+Run Tests
+=========
+
+.. program:: ctest
+
+.. option:: --preset <preset>, --preset=<preset>
-``--preset <preset>``, ``--preset=<preset>``
Use a test preset to specify test options. The project binary directory
is inferred from the ``configurePreset`` key. The current working directory
must contain CMake preset files.
See :manual:`preset <cmake-presets(7)>` for more details.
-``--list-presets``
+.. option:: --list-presets
+
Lists the available test presets. The current working directory must contain
CMake preset files.
-``-C <cfg>, --build-config <cfg>``
+.. option:: -C <cfg>, --build-config <cfg>
+
Choose configuration to test.
Some CMake-generated build trees can have multiple build
@@ -48,7 +65,8 @@ Options
which one should be tested. Example configurations are ``Debug`` and
``Release``.
-``--progress``
+.. option:: --progress
+
Enable short progress output from tests.
When the output of **ctest** is being sent directly to a terminal, the
@@ -61,40 +79,47 @@ Options
This option can also be enabled by setting the environment variable
:envvar:`CTEST_PROGRESS_OUTPUT`.
-``-V,--verbose``
+.. option:: -V, --verbose
+
Enable verbose output from tests.
Test output is normally suppressed and only summary information is
displayed. This option will show all test output.
-``-VV,--extra-verbose``
+.. option:: -VV, --extra-verbose
+
Enable more verbose output from tests.
Test output is normally suppressed and only summary information is
displayed. This option will show even more test output.
-``--debug``
+.. option:: --debug
+
Displaying more verbose internals of CTest.
This feature will result in a large number of output that is mostly
useful for debugging dashboard problems.
-``--output-on-failure``
+.. option:: --output-on-failure
+
Output anything outputted by the test program if the test should fail.
This option can also be enabled by setting the
:envvar:`CTEST_OUTPUT_ON_FAILURE` environment variable
-``--stop-on-failure``
+.. option:: --stop-on-failure
+
Stop running the tests when the first failure happens.
-``-F``
+.. option:: -F
+
Enable failover.
This option allows CTest to resume a test set execution that was
previously interrupted. If no interruption occurred, the ``-F`` option
will have no effect.
-``-j <jobs>, --parallel <jobs>``
+.. option:: -j <jobs>, --parallel <jobs>
+
Run the tests in parallel using the given number of jobs.
This option tells CTest to run the tests in parallel using given
@@ -105,7 +130,8 @@ Options
See `Label and Subproject Summary`_.
-``--resource-spec-file <file>``
+.. option:: --resource-spec-file <file>
+
Run CTest with :ref:`resource allocation <ctest-resource-allocation>` enabled,
using the
:ref:`resource specification file <ctest-resource-specification-file>`
@@ -114,40 +140,54 @@ Options
When ``ctest`` is run as a `Dashboard Client`_ this sets the
``ResourceSpecFile`` option of the `CTest Test Step`_.
-``--test-load <level>``
- While running tests in parallel (e.g. with ``-j``), try not to start
- tests when they may cause the CPU load to pass above a given threshold.
+.. option:: --test-load <level>
+
+ While running tests in parallel (e.g. with :option:`-j <ctest -j>`), try
+ not to start tests when they may cause the CPU load to pass above a given
+ threshold.
When ``ctest`` is run as a `Dashboard Client`_ this sets the
``TestLoad`` option of the `CTest Test Step`_.
-``-Q,--quiet``
+.. option:: -Q, --quiet
+
Make CTest quiet.
This option will suppress all the output. The output log file will
- still be generated if the ``--output-log`` is specified. Options such
- as ``--verbose``, ``--extra-verbose``, and ``--debug`` are ignored
+ still be generated if the :option:`--output-log <ctest --output-log>` is
+ specified. Options such as :option:`--verbose <ctest --verbose>`,
+ :option:`--extra-verbose <ctest --extra-verbose>`, and
+ :option:`--debug <ctest --debug>` are ignored
if ``--quiet`` is specified.
-``-O <file>, --output-log <file>``
+.. option:: -O <file>, --output-log <file>
+
Output to log file.
This option tells CTest to write all its output to a ``<file>`` log file.
-``--output-junit <file>``
+.. option:: --output-junit <file>
+
+ .. versionadded:: 3.21
+
Write test results in JUnit format.
This option tells CTest to write test results to ``<file>`` in JUnit XML
format. If ``<file>`` already exists, it will be overwritten. If using the
- ``-S`` option to run a dashboard script, use the ``OUTPUT_JUNIT`` keyword
- with the :command:`ctest_test` command instead.
+ :option:`-S <ctest -S>` option to run a dashboard script, use the
+ ``OUTPUT_JUNIT`` keyword with the :command:`ctest_test` command instead.
+
+.. option:: -N, --show-only[=<format>]
-``-N,--show-only[=<format>]``
Disable actual execution of tests.
This option tells CTest to list the tests that would be run but not
- actually run them. Useful in conjunction with the ``-R`` and ``-E``
- options.
+ actually run them. Useful in conjunction with the :option:`-R <ctest -R>`
+ and :option:`-E <ctest -E>` options.
+
+ .. versionadded:: 3.14
+
+ The ``--show-only`` option accepts a ``<format>`` value.
``<format>`` can be one of the following values.
@@ -159,7 +199,8 @@ Options
Dump the test information in JSON format.
See `Show as JSON Object Model`_.
-``-L <regex>, --label-regex <regex>``
+.. option:: -L <regex>, --label-regex <regex>
+
Run tests with labels matching regular expression as described under
:ref:`string(REGEX) <Regex Specification>`.
@@ -169,19 +210,22 @@ Options
of the test's labels (i.e. the multiple ``-L`` labels form an ``AND``
relationship). See `Label Matching`_.
-``-R <regex>, --tests-regex <regex>``
+.. option:: -R <regex>, --tests-regex <regex>
+
Run tests matching regular expression.
This option tells CTest to run only the tests whose names match the
given regular expression.
-``-E <regex>, --exclude-regex <regex>``
+.. option:: -E <regex>, --exclude-regex <regex>
+
Exclude tests matching regular expression.
This option tells CTest to NOT run the tests whose names match the
given regular expression.
-``-LE <regex>, --label-exclude <regex>``
+.. option:: -LE <regex>, --label-exclude <regex>
+
Exclude tests with labels matching regular expression.
This option tells CTest to NOT run the tests whose labels match the
@@ -190,7 +234,8 @@ Options
of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND``
relationship). See `Label Matching`_.
-``-FA <regex>, --fixture-exclude-any <regex>``
+.. option:: -FA <regex>, --fixture-exclude-any <regex>
+
Exclude fixtures matching ``<regex>`` from automatically adding any tests to
the test set.
@@ -201,72 +246,18 @@ Options
including test dependencies and skipping tests that have fixture setup tests
that fail.
-``-FS <regex>, --fixture-exclude-setup <regex>``
- Same as ``-FA`` except only matching setup tests are excluded.
-
-``-FC <regex>, --fixture-exclude-cleanup <regex>``
- Same as ``-FA`` except only matching cleanup tests are excluded.
-
-``-D <dashboard>, --dashboard <dashboard>``
- Execute dashboard test.
-
- This option tells CTest to act as a CDash client and perform a
- dashboard test. All tests are ``<Mode><Test>``, where ``<Mode>`` can be
- ``Experimental``, ``Nightly``, and ``Continuous``, and ``<Test>`` can be
- ``Start``, ``Update``, ``Configure``, ``Build``, ``Test``,
- ``Coverage``, and ``Submit``.
-
- See `Dashboard Client`_.
-
-``-D <var>:<type>=<value>``
- Define a variable for script mode.
-
- Pass in variable values on the command line. Use in conjunction
- with ``-S`` to pass variable values to a dashboard script. Parsing ``-D``
- arguments as variable values is only attempted if the value
- following ``-D`` does not match any of the known dashboard types.
-
-``-M <model>, --test-model <model>``
- Sets the model for a dashboard.
-
- This option tells CTest to act as a CDash client where the ``<model>``
- can be ``Experimental``, ``Nightly``, and ``Continuous``.
- Combining ``-M`` and ``-T`` is similar to ``-D``.
+.. option:: -FS <regex>, --fixture-exclude-setup <regex>
- See `Dashboard Client`_.
+ Same as :option:`-FA <ctest -FA>` except only matching setup tests are
+ excluded.
-``-T <action>, --test-action <action>``
- Sets the dashboard action to perform.
-
- This option tells CTest to act as a CDash client and perform some
- action such as ``start``, ``build``, ``test`` etc. See
- `Dashboard Client Steps`_ for the full list of actions.
- Combining ``-M`` and ``-T`` is similar to ``-D``.
+.. option:: -FC <regex>, --fixture-exclude-cleanup <regex>
- See `Dashboard Client`_.
+ Same as :option:`-FA <ctest -FA>` except only matching cleanup tests are
+ excluded.
-``-S <script>, --script <script>``
- Execute a dashboard for a configuration.
+.. option:: -I [Start,End,Stride,test#,test#|Test file], --tests-information
- This option tells CTest to load in a configuration script which sets
- a number of parameters such as the binary and source directories.
- Then CTest will do what is required to create and run a dashboard.
- This option basically sets up a dashboard and then runs ``ctest -D``
- with the appropriate options.
-
- See `Dashboard Client`_.
-
-``-SP <script>, --script-new-process <script>``
- Execute a dashboard for a configuration.
-
- This option does the same operations as ``-S`` but it will do them in a
- separate process. This is primarily useful in cases where the
- script may modify the environment and you do not want the modified
- environment to impact other ``-S`` scripts.
-
- See `Dashboard Client`_.
-
-``-I [Start,End,Stride,test#,test#|Test file], --tests-information``
Run a specific number of tests by number.
This option causes CTest to run tests starting at number ``Start``,
@@ -275,23 +266,29 @@ Options
``End``, or ``Stride`` can be empty. Optionally a file can be given that
contains the same syntax as the command line.
-``-U, --union``
- Take the Union of ``-I`` and ``-R``.
+.. option:: -U, --union
+
+ Take the Union of :option:`-I <ctest -I>` and :option:`-R <ctest -R>`.
+
+ When both :option:`-R <ctest -R>` and :option:`-I <ctest -I>` are specified
+ by default the intersection of tests are run. By specifying ``-U`` the union
+ of tests is run instead.
- When both ``-R`` and ``-I`` are specified by default the intersection of
- tests are run. By specifying ``-U`` the union of tests is run instead.
+.. option:: --rerun-failed
-``--rerun-failed``
Run only the tests that failed previously.
This option tells CTest to perform only the tests that failed during
its previous run. When this option is specified, CTest ignores all
- other options intended to modify the list of tests to run (``-L``, ``-R``,
- ``-E``, ``-LE``, ``-I``, etc). In the event that CTest runs and no tests
- fail, subsequent calls to CTest with the ``--rerun-failed`` option will run
- the set of tests that most recently failed (if any).
+ other options intended to modify the list of tests to run (
+ :option:`-L <ctest -L>`, :option:`-R <ctest -R>`, :option:`-E <ctest -E>`,
+ :option:`-LE <ctest -LE>`, :option:`-I <ctest -I>`, etc). In the event that
+ CTest runs and no tests fail, subsequent calls to CTest with the
+ ``--rerun-failed`` option will run the set of tests that most recently
+ failed (if any).
+
+.. option:: --repeat <mode>:<n>
-``--repeat <mode>:<n>``
Run tests repeatedly based on the given ``<mode>`` up to ``<n>`` times.
The modes are:
@@ -310,17 +307,20 @@ Options
This is useful in tolerating sporadic timeouts in test cases
on busy machines.
-``--repeat-until-fail <n>``
- Equivalent to ``--repeat until-fail:<n>``.
+.. option:: --repeat-until-fail <n>
+
+ Equivalent to :option:`--repeat until-fail:\<n\> <ctest --repeat>`.
+
+.. option:: --max-width <width>
-``--max-width <width>``
Set the max width for a test name to output.
Set the maximum width for each test name to show in the output.
This allows the user to widen the output to avoid clipping the test
name which can be very annoying.
-``--interactive-debug-mode [0|1]``
+.. option:: --interactive-debug-mode [0|1]
+
Set the interactive mode to ``0`` or ``1``.
This option causes CTest to run tests in either an interactive mode
@@ -332,7 +332,8 @@ Options
popup windows to appear. Now, due to CTest's use of ``libuv`` to launch
test processes, all system debug popup windows are always blocked.
-``--no-label-summary``
+.. option:: --no-label-summary
+
Disable timing summary information for labels.
This option tells CTest not to print summary information for each
@@ -341,7 +342,8 @@ Options
See `Label and Subproject Summary`_.
-``--no-subproject-summary``
+.. option:: --no-subproject-summary
+
Disable timing summary information for subprojects.
This option tells CTest not to print summary information for each
@@ -350,79 +352,95 @@ Options
See `Label and Subproject Summary`_.
-``--build-and-test``
-See `Build and Test Mode`_.
+.. option:: --test-dir <dir>
+
+ Specify the directory in which to look for tests.
-``--test-dir <dir>``
-Specify the directory in which to look for tests.
+.. option:: --test-output-size-passed <size>
-``--test-output-size-passed <size>``
.. versionadded:: 3.4
Limit the output for passed tests to ``<size>`` bytes.
-``--test-output-size-failed <size>``
+.. option:: --test-output-size-failed <size>
+
.. versionadded:: 3.4
Limit the output for failed tests to ``<size>`` bytes.
-``--test-output-truncation <mode>``
+.. option:: --test-output-truncation <mode>
+
.. versionadded:: 3.24
Truncate ``tail`` (default), ``middle`` or ``head`` of test output once
maximum output size is reached.
-``--overwrite``
+.. option:: --overwrite
+
Overwrite CTest configuration option.
By default CTest uses configuration options from configuration file.
This option will overwrite the configuration option.
-``--force-new-ctest-process``
+.. option:: --force-new-ctest-process
+
Run child CTest instances as new processes.
By default CTest will run child CTest instances within the same
process. If this behavior is not desired, this argument will
enforce new processes for child CTest processes.
-``--schedule-random``
+.. option:: --schedule-random
+
Use a random order for scheduling tests.
This option will run the tests in a random order. It is commonly
used to detect implicit dependencies in a test suite.
-``--submit-index``
+.. option:: --submit-index
+
Legacy option for old Dart2 dashboard server feature.
Do not use.
-``--timeout <seconds>``
+.. option:: --timeout <seconds>
+
Set the default test timeout.
This option effectively sets a timeout on all tests that do not
already have a timeout set on them via the :prop_test:`TIMEOUT`
property.
-``--stop-time <time>``
+.. option:: --stop-time <time>
+
Set a time at which all tests should stop running.
Set a real time of day at which all tests should timeout. Example:
``7:00:00 -0400``. Any time format understood by the curl date parser
is accepted. Local time is assumed if no timezone is specified.
-``--print-labels``
+.. option:: --print-labels
+
Print all available test labels.
This option will not run any tests, it will simply print the list of
all labels associated with the test set.
-``--no-tests=<[error|ignore]>``
- Regard no tests found either as error or ignore it.
+.. option:: --no-tests=<action>
+
+ Regard no tests found either as error (when ``<action>`` is set to
+ ``error``) or ignore it (when ``<action>`` is set to ``ignore``).
If no tests were found, the default behavior of CTest is to always log an
error message but to return an error code in script mode only. This option
unifies the behavior of CTest by either returning an error code if no tests
were found or by ignoring it.
+View Help
+=========
+
+To print version details or selected pages from the CMake documentation,
+use one of the following options:
+
.. include:: OPTIONS_HELP.txt
.. _`Label Matching`:
@@ -435,17 +453,17 @@ or excluded from a test run by filtering on the labels.
Each individual filter is a regular expression applied to
the labels attached to a test.
-When ``-L`` is used, in order for a test to be included in a
+When :option:`-L <ctest -L>` is used, in order for a test to be included in a
test run, each regular expression must match at least one
-label. Using more than one ``-L`` option means "match **all**
+label. Using more than one :option:`-L <ctest -L>` option means "match **all**
of these".
-The ``-LE`` option works just like ``-L``, but excludes tests
-rather than including them. A test is excluded if each regular
-expression matches at least one label.
+The :option:`-LE <ctest -LE>` option works just like :option:`-L <ctest -L>`,
+but excludes tests rather than including them. A test is excluded if each
+regular expression matches at least one label.
-If a test has no labels attached to it, then ``-L`` will never
-include that test, and ``-LE`` will never exclude that test.
+If a test has no labels attached to it, then :option:`-L <ctest -L>` will never
+include that test, and :option:`-LE <ctest -LE>` will never exclude that test.
As an example of tests with labels, consider five tests,
with the following labels:
@@ -532,62 +550,85 @@ be provided to use ``--build-and-test``. If ``--test-command`` is specified
then that will be run after the build is complete. Other options that affect
this mode include:
-``--build-target``
- Specify a specific target to build.
+.. option:: --build-and-test
- If left out the ``all`` target is built.
+ Switch into the build and test mode.
+
+.. option:: --build-target
+
+ Specify a specific target to build. The option can be given multiple times
+ with different targets, in which case each target is built in turn.
+ A clean will be done before building each target unless the
+ :option:`--build-noclean` option is given.
+
+ If no ``--build-target`` is specified, the ``all`` target is built.
+
+.. option:: --build-nocmake
-``--build-nocmake``
Run the build without running cmake first.
Skip the cmake step.
-``--build-run-dir``
+.. option:: --build-run-dir
+
Specify directory to run programs from.
Directory where programs will be after it has been compiled.
-``--build-two-config``
+.. option:: --build-two-config
+
Run CMake twice.
-``--build-exe-dir``
+.. option:: --build-exe-dir
+
Specify the directory for the executable.
-``--build-generator``
+.. option:: --build-generator
+
Specify the generator to use. See the :manual:`cmake-generators(7)` manual.
-``--build-generator-platform``
+.. option:: --build-generator-platform
+
Specify the generator-specific platform.
-``--build-generator-toolset``
+.. option:: --build-generator-toolset
+
Specify the generator-specific toolset.
-``--build-project``
+.. option:: --build-project
+
Specify the name of the project to build.
-``--build-makeprogram``
+.. option:: --build-makeprogram
+
Specify the explicit make program to be used by CMake when configuring and
building the project. Only applicable for Make and Ninja based generators.
-``--build-noclean``
+.. option:: --build-noclean
+
Skip the make clean step.
-``--build-config-sample``
+.. option:: --build-config-sample
+
A sample executable to use to determine the configuration that
should be used. e.g. ``Debug``, ``Release`` etc.
-``--build-options``
+.. option:: --build-options
+
Additional options for configuring the build (i.e. for CMake, not for
the build tool). Note that if this is specified, the ``--build-options``
keyword and its arguments must be the last option given on the command
line, with the possible exception of ``--test-command``.
-``--test-command``
- The command to run as the test step with the ``--build-and-test`` option.
+.. option:: --test-command
+
+ The command to run as the test step with the
+ :option:`--build-and-test <ctest --build-and-test>` option.
All arguments following this keyword will be assumed to be part of the
test command line, so it must be the last option given.
-``--test-timeout``
+.. option:: --test-timeout
+
The time limit in seconds
.. _`Dashboard Client`:
@@ -600,12 +641,80 @@ application. As a dashboard client, CTest performs a sequence of steps
to configure, build, and test software, and then submits the results to
a `CDash`_ server. The command-line signature used to submit to `CDash`_ is::
- ctest (-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>)
- [-- <dashboard-options>...]
+ ctest -D <dashboard> [-- <dashboard-options>...]
+ ctest -M <model> -T <action> [-- <dashboard-options>...]
+ ctest -S <script> [-- <dashboard-options>...]
+ ctest -SP <script> [-- <dashboard-options>...]
Options for Dashboard Client include:
-``--group <group>``
+.. option:: -D <dashboard>, --dashboard <dashboard>
+
+ Execute dashboard test.
+
+ This option tells CTest to act as a CDash client and perform a
+ dashboard test. All tests are ``<Mode><Test>``, where ``<Mode>`` can be
+ ``Experimental``, ``Nightly``, and ``Continuous``, and ``<Test>`` can be
+ ``Start``, ``Update``, ``Configure``, ``Build``, ``Test``,
+ ``Coverage``, and ``Submit``.
+
+ If ``<dashboard>`` is not one of the recognized ``<Mode><Test>`` values,
+ this will be treated as a variable definition instead (see the
+ :ref:`dashboard-options <Dashboard Options>` further below).
+
+.. option:: -M <model>, --test-model <model>
+
+ Sets the model for a dashboard.
+
+ This option tells CTest to act as a CDash client where the ``<model>``
+ can be ``Experimental``, ``Nightly``, and ``Continuous``.
+ Combining ``-M`` and :option:`-T <ctest -T>` is similar to
+ :option:`-D <ctest -D>`.
+
+.. option:: -T <action>, --test-action <action>
+
+ Sets the dashboard action to perform.
+
+ This option tells CTest to act as a CDash client and perform some
+ action such as ``start``, ``build``, ``test`` etc. See
+ `Dashboard Client Steps`_ for the full list of actions.
+ Combining :option:`-M <ctest -M>` and ``-T`` is similar to
+ :option:`-D <ctest -D>`.
+
+.. option:: -S <script>, --script <script>
+
+ Execute a dashboard for a configuration.
+
+ This option tells CTest to load in a configuration script which sets
+ a number of parameters such as the binary and source directories.
+ Then CTest will do what is required to create and run a dashboard.
+ This option basically sets up a dashboard and then runs :option:`ctest -D`
+ with the appropriate options.
+
+.. option:: -SP <script>, --script-new-process <script>
+
+ Execute a dashboard for a configuration.
+
+ This option does the same operations as :option:`-S <ctest -S>` but it
+ will do them in a separate process. This is primarily useful in cases
+ where the script may modify the environment and you do not want the modified
+ environment to impact other :option:`-S <ctest -S>` scripts.
+
+.. _`Dashboard Options`:
+
+The available ``<dashboard-options>`` are the following:
+
+.. option:: -D <var>:<type>=<value>
+
+ Define a variable for script mode.
+
+ Pass in variable values on the command line. Use in conjunction
+ with :option:`-S <ctest -S>` to pass variable values to a dashboard script.
+ Parsing ``-D`` arguments as variable values is only attempted if the value
+ following ``-D`` does not match any of the known dashboard types.
+
+.. option:: --group <group>
+
Specify what group you'd like to submit results to
Submit dashboard to specified group instead of default one. By
@@ -616,29 +725,34 @@ Options for Dashboard Client include:
This replaces the deprecated option ``--track``.
Despite the name change its behavior is unchanged.
-``-A <file>, --add-notes <file>``
+.. option:: -A <file>, --add-notes <file>
+
Add a notes file with submission.
This option tells CTest to include a notes file when submitting
dashboard.
-``--tomorrow-tag``
+.. option:: --tomorrow-tag
+
``Nightly`` or ``Experimental`` starts with next day tag.
This is useful if the build will not finish in one day.
-``--extra-submit <file>[;<file>]``
+.. option:: --extra-submit <file>[;<file>]
+
Submit extra files to the dashboard.
This option will submit extra files to the dashboard.
-``--http1.0``
+.. option:: --http1.0
+
Submit using `HTTP 1.0`.
This option will force CTest to use `HTTP 1.0` to submit files to the
dashboard, instead of `HTTP 1.1`.
-``--no-compress-output``
+.. option:: --no-compress-output
+
Do not compress test output when submitting.
This flag will turn off automatic compression of test output. Use
@@ -722,7 +836,7 @@ Run the ``ctest`` command with the current working directory set
to the build tree and use one of these signatures::
ctest -D <mode>[<step>]
- ctest -M <mode> [ -T <step> ]...
+ ctest -M <mode> [-T <step>]...
The ``<mode>`` must be one of the above `Dashboard Client Modes`_,
and each ``<step>`` must be one of the above `Dashboard Client Steps`_.
@@ -1027,9 +1141,9 @@ Configuration settings include:
``DefaultCTestConfigurationType``
When the build system to be launched allows build-time selection
of the configuration (e.g. ``Debug``, ``Release``), this specifies
- the default configuration to be built when no ``-C`` option is
- given to the ``ctest`` command. The value will be substituted into
- the value of ``MakeCommand`` to replace the literal string
+ the default configuration to be built when no :option:`-C <ctest -C>`
+ option is given to the ``ctest`` command. The value will be substituted
+ into the value of ``MakeCommand`` to replace the literal string
``${CTEST_CONFIGURATION_TYPE}`` if it appears.
* `CTest Script`_ variable: :variable:`CTEST_CONFIGURATION_TYPE`
@@ -1101,8 +1215,9 @@ Configuration settings include:
See `Label and Subproject Summary`_.
``TestLoad``
- While running tests in parallel (e.g. with ``-j``), try not to start
- tests when they may cause the CPU load to pass above a given threshold.
+ While running tests in parallel (e.g. with :option:`-j <ctest -j>`),
+ try not to start tests when they may cause the CPU load to pass above
+ a given threshold.
* `CTest Script`_ variable: :variable:`CTEST_TEST_LOAD`
* :module:`CTest` module variable: ``CTEST_TEST_LOAD``
@@ -1382,6 +1497,8 @@ Configuration settings include:
Show as JSON Object Model
=========================
+.. versionadded:: 3.14
+
When the ``--show-only=json-v1`` command line option is given, the test
information is output in JSON format. Version 1.0 of the JSON object
model is defined as follows:
@@ -1518,12 +1635,12 @@ Resource Specification File
---------------------------
The resource specification file is a JSON file which is passed to CTest, either
-on the :manual:`ctest(1)` command line as ``--resource-spec-file``, or as the
+on the command line as :option:`ctest --resource-spec-file`, or as the
``RESOURCE_SPEC_FILE`` argument of :command:`ctest_test`. If a dashboard script
is used and ``RESOURCE_SPEC_FILE`` is not specified, the value of
:variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script is used instead.
-If ``--resource-spec-file``, ``RESOURCE_SPEC_FILE``, and
-:variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified,
+If :option:`--resource-spec-file <ctest --resource-spec-file>`, ``RESOURCE_SPEC_FILE``,
+and :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified,
the value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used
instead. If none of these are specified, no resource spec file is used.
diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json
index be5c791c8..696ab4721 100644
--- a/Help/manual/presets/example.json
+++ b/Help/manual/presets/example.json
@@ -1,5 +1,5 @@
{
- "version": 5,
+ "version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
@@ -66,6 +66,38 @@
"execution": {"noTestsAction": "error", "stopOnFailure": true}
}
],
+ "packagePresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "generators": [
+ "TGZ"
+ ]
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ },
+ {
+ "type": "build",
+ "name": "default"
+ },
+ {
+ "type": "test",
+ "name": "default"
+ },
+ {
+ "type": "package",
+ "name": "default"
+ }
+ ]
+ }
+ ],
"vendor": {
"example.com/ExampleIDE/1.0": {
"autoFormat": false
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index c96405c11..348116b38 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -72,6 +72,23 @@
"include": { "$ref": "#/definitions/include"}
},
"additionalProperties": false
+ },
+ {
+ "properties": {
+ "version": {
+ "const": 6,
+ "description": "A required integer representing the version of the JSON schema."
+ },
+ "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"},
+ "vendor": { "$ref": "#/definitions/vendor" },
+ "configurePresets": { "$ref": "#/definitions/configurePresetsV3"},
+ "buildPresets": { "$ref": "#/definitions/buildPresetsV4"},
+ "testPresets": { "$ref": "#/definitions/testPresetsV6"},
+ "packagePresets": { "$ref": "#/definitions/packagePresetsV6"},
+ "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" },
+ "include": { "$ref": "#/definitions/include"}
+ },
+ "additionalProperties": false
}
],
"required": [
@@ -476,12 +493,12 @@
"properties": {
"name": {
"type": "string",
- "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
"minLength": 1
},
"hidden": {
"type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
},
"inherits": {
"anyOf": [
@@ -688,6 +705,25 @@
"additionalProperties": false
}
},
+ "testPresetsItemsV6": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 6 and higher.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "properties": {
+ "outputJUnitFile": {
+ "type": "string",
+ "description": "An optional string specifying a path to a JUnit file. Equivalent to passing --output-junit on the command line."
+ }
+ }
+ }
+ }
+ }
+ },
"testPresetsItemsV5": {
"type": "array",
"description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 5 and higher.",
@@ -728,12 +764,12 @@
"properties": {
"name": {
"type": "string",
- "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
"minLength": 1
},
"hidden": {
"type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
},
"inherits": {
"anyOf": [
@@ -1034,6 +1070,58 @@
]
}
},
+ "testPresetsV6": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 6 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/testPresetsItemsV2" },
+ { "$ref": "#/definitions/testPresetsItemsV3" },
+ { "$ref": "#/definitions/testPresetsItemsV5" },
+ { "$ref": "#/definitions/testPresetsItemsV6" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "configuration": {},
+ "overwriteConfigurationFile": {},
+ "output": {
+ "type": "object",
+ "properties": {
+ "shortProgress": {},
+ "verbosity": {},
+ "debug": {},
+ "outputOnFailure": {},
+ "quiet": {},
+ "outputLogFile": {},
+ "outputJUnitFile": {},
+ "labelSummary": {},
+ "subprojectSummary": {},
+ "maxPassedTestOutputSize": {},
+ "maxFailedTestOutputSize": {},
+ "maxTestNameWidth": {},
+ "testOutputTruncation": {}
+ },
+ "additionalProperties": false
+ },
+ "filter": {},
+ "execution": {},
+ "condition": {}
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
"testPresetsV5": {
"type": "array",
"description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 5 and higher.",
@@ -1056,7 +1144,24 @@
"environment": {},
"configuration": {},
"overwriteConfigurationFile": {},
- "output": {},
+ "output": {
+ "type": "object",
+ "properties": {
+ "shortProgress": {},
+ "verbosity": {},
+ "debug": {},
+ "outputOnFailure": {},
+ "quiet": {},
+ "outputLogFile": {},
+ "labelSummary": {},
+ "subprojectSummary": {},
+ "maxPassedTestOutputSize": {},
+ "maxFailedTestOutputSize": {},
+ "maxTestNameWidth": {},
+ "testOutputTruncation": {}
+ },
+ "additionalProperties": false
+ },
"filter": {},
"execution": {},
"condition": {}
@@ -1088,7 +1193,23 @@
"environment": {},
"configuration": {},
"overwriteConfigurationFile": {},
- "output": {},
+ "output": {
+ "type": "object",
+ "properties": {
+ "shortProgress": {},
+ "verbosity": {},
+ "debug": {},
+ "outputOnFailure": {},
+ "quiet": {},
+ "outputLogFile": {},
+ "labelSummary": {},
+ "subprojectSummary": {},
+ "maxPassedTestOutputSize": {},
+ "maxFailedTestOutputSize": {},
+ "maxTestNameWidth": {}
+ },
+ "additionalProperties": false
+ },
"filter": {},
"execution": {},
"condition": {}
@@ -1119,7 +1240,23 @@
"environment": {},
"configuration": {},
"overwriteConfigurationFile": {},
- "output": {},
+ "output": {
+ "type": "object",
+ "properties": {
+ "shortProgress": {},
+ "verbosity": {},
+ "debug": {},
+ "outputOnFailure": {},
+ "quiet": {},
+ "outputLogFile": {},
+ "labelSummary": {},
+ "subprojectSummary": {},
+ "maxPassedTestOutputSize": {},
+ "maxFailedTestOutputSize": {},
+ "maxTestNameWidth": {}
+ },
+ "additionalProperties": false
+ },
"filter": {},
"execution": {}
},
@@ -1129,6 +1266,260 @@
"additionalProperties": false
}
},
+ "packagePresetsItemsV6": {
+ "type": "array",
+ "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 6 and higher.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "minLength": 1
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "inherits": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the name of the package preset to inherit from.",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of package presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of the preset to inherit from.",
+ "minLength": 1
+ }
+ }
+ ]
+ },
+ "configurePreset": {
+ "type": "string",
+ "description": "An optional string specifying the name of a configure preset to associate with this package preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
+ "minLength": 1
+ },
+ "vendor": {
+ "type": "object",
+ "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field. If vendors use their own per-preset vendor field, they should implement inheritance in a sensible manner when appropriate.",
+ "properties": {}
+ },
+ "displayName": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "inheritConfigureEnvironment": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited package preset environments, but before environment variables explicitly specified in this package preset."
+ },
+ "environment": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ },
+ "propertyNames": {
+ "pattern": "^.+$"
+ }
+ },
+ "condition": { "$ref": "#/definitions/topCondition" },
+ "generators": {
+ "type": "array",
+ "description": "An optional list of strings representing generators for CPack to use.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of the CPack generator to use."
+ }
+ },
+ "configurations": {
+ "type": "array",
+ "description": "An optional list of strings representing build configurations for CPack to package.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of the configuration to use."
+ }
+ },
+ "variables": {
+ "type": "object",
+ "description": "An optional map of variables to pass to CPack, equivalent to -D arguments. Each key is the name of a variable, and the value is the string to assign to that variable.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the value of the variable."
+ }
+ },
+ "configFile": {
+ "type": "string",
+ "description": "An optional string representing the config file for CPack to use."
+ },
+ "output": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "properties": {
+ "debug": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not to print debug information. A value of true is equivalent to passing --debug on the command line."
+ },
+ "verbose": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not to print verbosely. A value of true is equivalent to passing --verbose on the command line."
+ }
+ },
+ "additionalProperties": false
+ },
+ "packageName": {
+ "type": "string",
+ "description": "An optional string representing the package name."
+ },
+ "packageVersion": {
+ "type": "string",
+ "description": "An optional string representing the package version."
+ },
+ "packageDirectory": {
+ "type": "string",
+ "description": "An optional string representing the directory in which to place the package."
+ },
+ "vendorName": {
+ "type": "string",
+ "description": "An optional string representing the vendor name."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "packagePresetsV6": {
+ "type": "array",
+ "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 6 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/packagePresetsItemsV6" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "condition": {},
+ "generators": {},
+ "configurations": {},
+ "variables": {},
+ "configFile": {},
+ "output": {},
+ "packageName": {},
+ "packageVersion": {},
+ "packageDirectory": {},
+ "vendorName": {}
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "workflowPresetsItemsV6": {
+ "type": "array",
+ "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "minLength": 1
+ },
+ "vendor": {
+ "type": "object",
+ "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field.",
+ "properties": {}
+ },
+ "displayName": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "steps": {
+ "type": "array",
+ "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string. The first step must be configure. Subsequent steps must be either build, test, or package.",
+ "enum": ["configure", "build", "test", "package"]
+ },
+ "name": {
+ "type": "string",
+ "description": "A required string representing the name of the configure, build, test, or package preset to run as this workflow step.",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "type",
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ }
+ },
+ "required": [
+ "name",
+ "steps"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "workflowPresetsV6": {
+ "type": "array",
+ "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/workflowPresetsItemsV6" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "steps": {}
+ },
+ "required": [
+ "name",
+ "steps"
+ ],
+ "additionalProperties": false
+ }
+ },
"condition": {
"anyOf": [
{
diff --git a/Help/module/FindOpenSP.rst b/Help/module/FindOpenSP.rst
new file mode 100644
index 000000000..1a3da0173
--- /dev/null
+++ b/Help/module/FindOpenSP.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindOpenSP.cmake
diff --git a/Help/module/FindSDL_gfx.rst b/Help/module/FindSDL_gfx.rst
new file mode 100644
index 000000000..e05d661ea
--- /dev/null
+++ b/Help/module/FindSDL_gfx.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindSDL_gfx.cmake
diff --git a/Help/policy/CMP0058.rst b/Help/policy/CMP0058.rst
index 06cc74b5f..faab1cbdc 100644
--- a/Help/policy/CMP0058.rst
+++ b/Help/policy/CMP0058.rst
@@ -50,7 +50,7 @@ that ensure ``byproduct.txt`` will exist before its consumers
need it. See discussion of this problem in `Ninja Issue 760`_
for further details on why Ninja works this way.
-.. _`Ninja Issue 760`: https://github.com/martine/ninja/issues/760
+.. _Ninja Issue 760: https://github.com/ninja-build/ninja/issues/760
Instead of leaving byproducts undeclared in the rules that generate
them, Ninja expects byproducts to be listed along with other outputs.
@@ -71,6 +71,9 @@ every custom command dependency, even on source files, needs to
be treated this way because CMake does not have enough information
to know which files are generated as byproducts of custom commands.
+Introducing Byproducts
+^^^^^^^^^^^^^^^^^^^^^^
+
CMake 3.2 introduced the ``BYPRODUCTS`` option to the
:command:`add_custom_command` and :command:`add_custom_target`
commands. This option allows byproducts to be specified explicitly:
diff --git a/Help/policy/CMP0140.rst b/Help/policy/CMP0140.rst
new file mode 100644
index 000000000..dea8989e1
--- /dev/null
+++ b/Help/policy/CMP0140.rst
@@ -0,0 +1,17 @@
+CMP0140
+-------
+
+.. versionadded:: 3.25
+
+The :command:`return` command checks its parameters.
+
+The ``OLD`` behavior for this policy is to ignore any parameters given to the
+command.
+The ``NEW`` behavior is to check the validity of the parameters.
+
+This policy was introduced in CMake version 3.25.
+CMake version |release| warns when the policy is not set and uses
+``OLD`` behavior. Use the :command:`cmake_policy` command to set
+it to ``OLD`` or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0141.rst b/Help/policy/CMP0141.rst
new file mode 100644
index 000000000..970e41db2
--- /dev/null
+++ b/Help/policy/CMP0141.rst
@@ -0,0 +1,55 @@
+CMP0141
+-------
+
+.. versionadded:: 3.25
+
+MSVC debug information format flags are selected by an abstraction.
+
+Compilers targeting the MSVC ABI have flags to select the debug information
+format. Debug information format selection typically varies with build
+configuration.
+
+In CMake 3.24 and below, debug information format flags are added to
+the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache entries by CMake
+automatically. This allows users to edit their cache entries to adjust the
+flags. However, the presence of such default flags is problematic for
+projects that want to choose a different runtime library programmatically.
+In particular, it requires string editing of the
+:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` variables with knowledge of the
+CMake builtin defaults so they can be replaced.
+
+CMake 3.25 and above prefer to leave the debug information format flags
+out of the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values and instead
+offer a first-class abstraction. The
+:variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` variable and
+:prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` target property may be set to
+select the MSVC debug information format. If they are not set, CMake
+enables debug information in debug configurations using the default value
+``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if supported by the
+compiler, and otherwise ``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``.
+
+This policy provides compatibility with projects that have not been updated
+to be aware of the abstraction. The policy setting takes effect as of the
+first :command:`project` or :command:`enable_language` command that enables
+a language whose compiler targets the MSVC ABI.
+
+.. note::
+
+ Once the policy has taken effect at the top of a project, that choice
+ will be used throughout the tree. In projects that have nested projects
+ in subdirectories, be sure to confirm if everything is working with the
+ selected policy behavior.
+
+The ``OLD`` behavior for this policy is to place MSVC debug information
+format flags in the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache
+entries and ignore the :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT`
+abstraction. The ``NEW`` behavior for this policy is to *not* place MSVC
+debug information format flags in the default cache entries and use
+the abstraction instead.
+
+This policy was introduced in CMake version 3.25. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0142.rst b/Help/policy/CMP0142.rst
new file mode 100644
index 000000000..1f928f079
--- /dev/null
+++ b/Help/policy/CMP0142.rst
@@ -0,0 +1,27 @@
+CMP0142
+-------
+
+.. versionadded:: 3.25
+
+The :generator:`Xcode` generator does not append per-config suffixes to
+library search paths.
+
+In CMake 3.24 and below, the :generator:`Xcode` generator preceded each
+entry of a library search path with a copy of itself appended with
+``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)``. This was left from
+very early versions of CMake in which per-config directories were not well
+modeled. Such paths often do not exist, resulting in warnings from the
+toolchain. CMake 3.25 and above prefer to not add such library search
+paths. This policy provides compatibility for projects that may have been
+accidentally relying on the old behavior.
+
+The ``OLD`` behavior for this policy is to append
+``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)`` to all library search paths.
+The ``NEW`` behavior is to not modify library search paths.
+
+This policy was introduced in CMake version 3.25. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_dir/SYSTEM.rst b/Help/prop_dir/SYSTEM.rst
new file mode 100644
index 000000000..4f923b797
--- /dev/null
+++ b/Help/prop_dir/SYSTEM.rst
@@ -0,0 +1,10 @@
+SYSTEM
+------
+
+.. versionadded:: 3.25
+
+This directory property is used to initialize the :prop_tgt:`SYSTEM`
+target property for targets created in that directory. It is set to
+true by :command:`add_subdirectory` and
+:command:`FetchContent_Declare` when the ``SYSTEM`` option is given
+as an argument to those commands.
diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
index d93a9c1f8..a31ee3aae 100644
--- a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
@@ -36,4 +36,9 @@ The features known to this version of CMake are:
Compiler mode is at least CUDA/C++ 23.
+``cuda_std_26``
+ .. versionadded:: 3.25
+
+ Compiler mode is at least CUDA/C++ 26.
+
.. include:: CMAKE_LANG_STD_FLAGS.txt
diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
index 68468508f..e54b927c4 100644
--- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -46,6 +46,11 @@ but it does not necessarily imply complete conformance to that standard.
Compiler mode is at least C++ 23.
+``cxx_std_26``
+ .. versionadded:: 3.25
+
+ Compiler mode is at least C++ 26.
+
.. include:: CMAKE_LANG_STD_FLAGS.txt
Low level individual compile features
@@ -74,233 +79,233 @@ Individual features from C++ 11
``cxx_alias_templates``
Template aliases, as defined in N2258_.
- .. _N2258: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf
+ .. _N2258: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf
``cxx_alignas``
Alignment control ``alignas``, as defined in N2341_.
- .. _N2341: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf
+ .. _N2341: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf
``cxx_alignof``
Alignment control ``alignof``, as defined in N2341_.
- .. _N2341: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf
+ .. _N2341: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf
``cxx_attributes``
Generic attributes, as defined in N2761_.
- .. _N2761: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf
+ .. _N2761: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf
``cxx_auto_type``
Automatic type deduction, as defined in N1984_.
- .. _N1984: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf
+ .. _N1984: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf
``cxx_constexpr``
Constant expressions, as defined in N2235_.
- .. _N2235: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
+ .. _N2235: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
``cxx_decltype_incomplete_return_types``
Decltype on incomplete return types, as defined in N3276_.
- .. _N3276 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf
+ .. _N3276 : https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf
``cxx_decltype``
Decltype, as defined in N2343_.
- .. _N2343: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf
+ .. _N2343: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf
``cxx_default_function_template_args``
Default template arguments for function templates, as defined in DR226_
- .. _DR226: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226
+ .. _DR226: https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226
``cxx_defaulted_functions``
Defaulted functions, as defined in N2346_.
- .. _N2346: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
+ .. _N2346: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
``cxx_defaulted_move_initializers``
Defaulted move initializers, as defined in N3053_.
- .. _N3053: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html
+ .. _N3053: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html
``cxx_delegating_constructors``
Delegating constructors, as defined in N1986_.
- .. _N1986: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
+ .. _N1986: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
``cxx_deleted_functions``
Deleted functions, as defined in N2346_.
- .. _N2346: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
+ .. _N2346: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
``cxx_enum_forward_declarations``
Enum forward declarations, as defined in N2764_.
- .. _N2764: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf
+ .. _N2764: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf
``cxx_explicit_conversions``
Explicit conversion operators, as defined in N2437_.
- .. _N2437: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf
+ .. _N2437: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf
``cxx_extended_friend_declarations``
Extended friend declarations, as defined in N1791_.
- .. _N1791: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf
+ .. _N1791: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf
``cxx_extern_templates``
Extern templates, as defined in N1987_.
- .. _N1987: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm
+ .. _N1987: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm
``cxx_final``
Override control ``final`` keyword, as defined in N2928_, N3206_ and N3272_.
- .. _N2928: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm
- .. _N3206: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm
- .. _N3272: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm
+ .. _N2928: https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm
+ .. _N3206: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm
+ .. _N3272: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm
``cxx_func_identifier``
Predefined ``__func__`` identifier, as defined in N2340_.
- .. _N2340: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm
+ .. _N2340: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm
``cxx_generalized_initializers``
Initializer lists, as defined in N2672_.
- .. _N2672: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm
+ .. _N2672: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm
``cxx_inheriting_constructors``
Inheriting constructors, as defined in N2540_.
- .. _N2540: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm
+ .. _N2540: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm
``cxx_inline_namespaces``
Inline namespaces, as defined in N2535_.
- .. _N2535: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm
+ .. _N2535: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm
``cxx_lambdas``
Lambda functions, as defined in N2927_.
- .. _N2927: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf
+ .. _N2927: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf
``cxx_local_type_template_args``
Local and unnamed types as template arguments, as defined in N2657_.
- .. _N2657: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm
+ .. _N2657: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm
``cxx_long_long_type``
``long long`` type, as defined in N1811_.
- .. _N1811: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf
+ .. _N1811: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf
``cxx_noexcept``
Exception specifications, as defined in N3050_.
- .. _N3050: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html
+ .. _N3050: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html
``cxx_nonstatic_member_init``
Non-static data member initialization, as defined in N2756_.
- .. _N2756: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2756.htm
+ .. _N2756: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2756.htm
``cxx_nullptr``
Null pointer, as defined in N2431_.
- .. _N2431: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
+ .. _N2431: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
``cxx_override``
Override control ``override`` keyword, as defined in N2928_, N3206_
and N3272_.
- .. _N2928: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm
- .. _N3206: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm
- .. _N3272: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm
+ .. _N2928: https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm
+ .. _N3206: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm
+ .. _N3272: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm
``cxx_range_for``
Range-based for, as defined in N2930_.
- .. _N2930: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html
+ .. _N2930: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html
``cxx_raw_string_literals``
Raw string literals, as defined in N2442_.
- .. _N2442: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
+ .. _N2442: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
``cxx_reference_qualified_functions``
Reference qualified functions, as defined in N2439_.
- .. _N2439: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm
+ .. _N2439: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm
``cxx_right_angle_brackets``
Right angle bracket parsing, as defined in N1757_.
- .. _N1757: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
+ .. _N1757: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
``cxx_rvalue_references``
R-value references, as defined in N2118_.
- .. _N2118: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
+ .. _N2118: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
``cxx_sizeof_member``
Size of non-static data members, as defined in N2253_.
- .. _N2253: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html
+ .. _N2253: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html
``cxx_static_assert``
Static assert, as defined in N1720_.
- .. _N1720: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html
+ .. _N1720: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html
``cxx_strong_enums``
Strongly typed enums, as defined in N2347_.
- .. _N2347: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf
+ .. _N2347: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf
``cxx_thread_local``
Thread-local variables, as defined in N2659_.
- .. _N2659: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm
+ .. _N2659: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm
``cxx_trailing_return_types``
Automatic function return type, as defined in N2541_.
- .. _N2541: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm
+ .. _N2541: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm
``cxx_unicode_literals``
Unicode string literals, as defined in N2442_.
- .. _N2442: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
+ .. _N2442: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
``cxx_uniform_initialization``
Uniform initialization, as defined in N2640_.
- .. _N2640: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2640.pdf
+ .. _N2640: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2640.pdf
``cxx_unrestricted_unions``
Unrestricted unions, as defined in N2544_.
- .. _N2544: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
+ .. _N2544: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
``cxx_user_literals``
User-defined literals, as defined in N2765_.
- .. _N2765: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf
+ .. _N2765: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf
``cxx_variadic_macros``
Variadic macros, as defined in N1653_.
- .. _N1653: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm
+ .. _N1653: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm
``cxx_variadic_templates``
Variadic templates, as defined in N2242_.
- .. _N2242: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
+ .. _N2242: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
Individual features from C++ 14
@@ -309,54 +314,54 @@ Individual features from C++ 14
``cxx_aggregate_default_initializers``
Aggregate default initializers, as defined in N3605_.
- .. _N3605: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3605.html
+ .. _N3605: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3605.html
``cxx_attribute_deprecated``
``[[deprecated]]`` attribute, as defined in N3760_.
- .. _N3760: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html
+ .. _N3760: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html
``cxx_binary_literals``
Binary literals, as defined in N3472_.
- .. _N3472: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf
+ .. _N3472: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf
``cxx_contextual_conversions``
Contextual conversions, as defined in N3323_.
- .. _N3323: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf
+ .. _N3323: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf
``cxx_decltype_auto``
``decltype(auto)`` semantics, as defined in N3638_.
- .. _N3638: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html
+ .. _N3638: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html
``cxx_digit_separators``
Digit separators, as defined in N3781_.
- .. _N3781: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
+ .. _N3781: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
``cxx_generic_lambdas``
Generic lambdas, as defined in N3649_.
- .. _N3649: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html
+ .. _N3649: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html
``cxx_lambda_init_captures``
Initialized lambda captures, as defined in N3648_.
- .. _N3648: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.html
+ .. _N3648: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.html
``cxx_relaxed_constexpr``
Relaxed constexpr, as defined in N3652_.
- .. _N3652: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html
+ .. _N3652: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html
``cxx_return_type_deduction``
Return type deduction on normal functions, as defined in N3386_.
- .. _N3386: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3386.html
+ .. _N3386: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3386.html
``cxx_variable_templates``
Variable templates, as defined in N3651_.
- .. _N3651: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3651.pdf
+ .. _N3651: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3651.pdf
diff --git a/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst b/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst
index fb8807f31..e70eeb4d7 100644
--- a/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst
+++ b/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst
@@ -3,7 +3,7 @@ CPACK_START_MENU_SHORTCUTS
.. versionadded:: 3.3
-Species a list of shortcut names that should be created in the `Start Menu`
+Species a list of shortcut names that should be created in the ``Start Menu``
for this file.
The property is currently only supported by the :cpack_gen:`CPack WIX Generator`.
diff --git a/Help/prop_test/FIXTURES_REQUIRED.rst b/Help/prop_test/FIXTURES_REQUIRED.rst
index f85083069..7a056012b 100644
--- a/Help/prop_test/FIXTURES_REQUIRED.rst
+++ b/Help/prop_test/FIXTURES_REQUIRED.rst
@@ -19,10 +19,11 @@ be executed. The cleanup tests for the fixture will always be executed, even if
some setup tests fail.
When CTest is asked to execute only a subset of tests (e.g. by the use of
-regular expressions or when run with the ``--rerun-failed`` command line
-option), it will automatically add any setup or cleanup tests for fixtures
-required by any of the tests that are in the execution set. This behavior can
-be overridden with the ``-FS``, ``-FC`` and ``-FA`` command line options to
+regular expressions or when run with the :option:`--rerun-failed <ctest --rerun-failed>`
+command line option), it will automatically add any setup or cleanup tests for
+fixtures required by any of the tests that are in the execution set. This
+behavior can be overridden with the :option:`-FS <ctest -FS>`,
+:option:`-FC <ctest -FC>` and :option:`-FA <ctest -FA>` command line options to
:manual:`ctest(1)` if desired.
Since setup and cleanup tasks are also tests, they can have an ordering
diff --git a/Help/prop_test/LABELS.rst b/Help/prop_test/LABELS.rst
index a06f15274..d827adc08 100644
--- a/Help/prop_test/LABELS.rst
+++ b/Help/prop_test/LABELS.rst
@@ -4,7 +4,7 @@ LABELS
Specify a list of text labels associated with a test. The labels are
reported in both the ``ctest`` output summary and in dashboard submissions.
They can also be used to filter the set of tests to be executed (see the
-``ctest -L`` and ``ctest -LE`` :ref:`CTest Options`).
+:option:`ctest -L` and :option:`ctest -LE` options).
See :ref:`Additional Labels` for adding labels to a test dynamically during
test execution.
diff --git a/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst
index 19323cb39..0d2b29596 100644
--- a/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst
+++ b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst
@@ -5,8 +5,8 @@ COMPILE_WARNING_AS_ERROR
Specify whether to treat warnings on compile as errors.
If enabled, adds a flag to treat warnings on compile as errors.
-If the ``--compile-no-warning-as-error`` option is given on the
-:manual:`cmake(1)` command line, this property is ignored.
+If the :option:`cmake --compile-no-warning-as-error` option is given
+on the :manual:`cmake(1)` command line, this property is ignored.
This property is not implemented for all compilers. It is silently ignored
if there is no implementation for the compiler being used. The currently
@@ -26,10 +26,12 @@ implemented :variable:`compiler IDs <CMAKE_<LANG>_COMPILER_ID>` are:
* ``NVIDIA`` (CUDA)
* ``QCC``
* ``SunPro``
+* ``Tasking``
* ``TI``
* ``VisualAge``
* ``XL``
* ``XLClang``
This property is initialized by the value of the variable
-:variable:`CMAKE_COMPILE_WARNING_AS_ERROR` if it is set when a target is created.
+:variable:`CMAKE_COMPILE_WARNING_AS_ERROR` if it is set when a target is
+created.
diff --git a/Help/prop_tgt/CONFIG_POSTFIX.rst b/Help/prop_tgt/CONFIG_POSTFIX.rst
index 5c2fbd75f..69caa39d5 100644
--- a/Help/prop_tgt/CONFIG_POSTFIX.rst
+++ b/Help/prop_tgt/CONFIG_POSTFIX.rst
@@ -1,13 +1,13 @@
<CONFIG>_POSTFIX
----------------
-Postfix to append to the target file name for configuration <CONFIG>.
+Postfix to append to the target file name for configuration ``<CONFIG>``.
-When building with configuration <CONFIG> the value of this property
+When building with configuration ``<CONFIG>`` the value of this property
is appended to the target file name built on disk. For non-executable
-targets, this property is initialized by the value of the variable
-CMAKE_<CONFIG>_POSTFIX if it is set when a target is created. This
-property is ignored on the Mac for Frameworks and App Bundles.
+targets, this property is initialized by the value of the
+:variable:`CMAKE_<CONFIG>_POSTFIX` variable if it is set when a target is
+created. This property is ignored on macOS for Frameworks and App Bundles.
For macOS see also the :prop_tgt:`FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>`
target property.
diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst
index 950ba12e6..ada69b93f 100644
--- a/Help/prop_tgt/CUDA_STANDARD.rst
+++ b/Help/prop_tgt/CUDA_STANDARD.rst
@@ -39,6 +39,12 @@ Supported values are:
CUDA C++23
+``26``
+ .. versionadded:: 3.25
+
+ CUDA C++26. CMake 3.25 and later *recognize* ``26`` as a valid value,
+ no version has support for any compiler.
+
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
means that using:
diff --git a/Help/prop_tgt/CXX_MODULE_DIRS.rst b/Help/prop_tgt/CXX_MODULE_DIRS.rst
new file mode 100644
index 000000000..a32b5b178
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_DIRS.rst
@@ -0,0 +1,19 @@
+CXX_MODULE_DIRS
+---------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's default
+C++ module set (i.e. the file set with name and type ``CXX_MODULES``). The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_DIRS_<NAME>` for the list of base directories in
+other C++ module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst
new file mode 100644
index 000000000..919099105
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst
@@ -0,0 +1,19 @@
+CXX_MODULE_DIRS_<NAME>
+----------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's ``<NAME>`` C++
+module set, which has the set type ``CXX_MODULES``. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_DIRS` for the list of base directories in the
+default C++ module set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names
+of all C++ module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst
new file mode 100644
index 000000000..5f33111a6
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst
@@ -0,0 +1,19 @@
+CXX_MODULE_HEADER_UNIT_DIRS
+---------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's default C++
+module header set (i.e. the file set with name and type
+``CXX_MODULE_HEADER_UNITS``). The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>` for the list of base
+directories in other C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst
new file mode 100644
index 000000000..b6163da0a
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst
@@ -0,0 +1,21 @@
+CXX_MODULE_HEADER_UNIT_DIRS_<NAME>
+----------------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's ``<NAME>`` C++
+module header set, which has the set type ``CXX_MODULE_HEADER_UNITS``. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS` for the list of base directories
+in the default C++ module header set. See
+:prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for the file set names of all C++
+module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst
new file mode 100644
index 000000000..3b1bd042e
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst
@@ -0,0 +1,20 @@
+CXX_MODULE_HEADER_UNIT_SET
+--------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's default C++ module header
+set, (i.e. the file set with name and type ``CXX_MODULE_HEADER_UNITS``). If
+any of the paths are relative, they are computed relative to the target's
+source directory. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>` for the list of files in
+other C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst
new file mode 100644
index 000000000..ffc2daf9c
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst
@@ -0,0 +1,20 @@
+CXX_MODULE_HEADER_UNIT_SETS
+---------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module header
+sets (i.e. all file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files
+listed in these file sets are treated as source files for the purpose of IDE
+integration.
+
+C++ module header sets may be defined using the :command:`target_sources`
+command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``.
+
+See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>`,
+:prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` and
+:prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS`.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst
new file mode 100644
index 000000000..4bf5069d8
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst
@@ -0,0 +1,21 @@
+CXX_MODULE_HEADER_UNIT_SET_<NAME>
+---------------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's ``<NAME>`` C++ module header
+set, which has the set type ``CXX_MODULE_HEADER_UNITS``. If any of the paths
+are relative, they are computed relative to the target's source directory. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` for the list of files in the
+default C++ module header set. See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for
+the file set names of all C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_SET.rst b/Help/prop_tgt/CXX_MODULE_SET.rst
new file mode 100644
index 000000000..f5cd8b2c2
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SET.rst
@@ -0,0 +1,20 @@
+CXX_MODULE_SET
+--------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's default C++ module set,
+(i.e. the file set with name and type ``CXX_MODULES``). If any of the paths
+are relative, they are computed relative to the target's source directory. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_SET_<NAME>` for the list of files in other C++
+module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_SETS.rst b/Help/prop_tgt/CXX_MODULE_SETS.rst
new file mode 100644
index 000000000..0e8945ad0
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SETS.rst
@@ -0,0 +1,18 @@
+CXX_MODULE_SETS
+---------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module sets (i.e.
+all file sets with the type ``CXX_MODULES``). Files listed in these file sets
+are treated as source files for the purpose of IDE integration.
+
+C++ module sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``CXX_MODULES``.
+
+See also :prop_tgt:`CXX_MODULE_SET_<NAME>`, :prop_tgt:`CXX_MODULE_SET` and
+:prop_tgt:`INTERFACE_CXX_MODULE_SETS`.
diff --git a/Help/prop_tgt/CXX_MODULE_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst
new file mode 100644
index 000000000..5674c9980
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst
@@ -0,0 +1,20 @@
+CXX_MODULE_SET_<NAME>
+---------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's ``<NAME>`` C++ module set,
+which has the set type ``CXX_MODULES``. If any of the paths are relative, they
+are computed relative to the target's source directory. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_SET` for the list of files in the default C++ module
+set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names of all C++ module
+sets.
diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst
index b10d20173..9b381e421 100644
--- a/Help/prop_tgt/CXX_STANDARD.rst
+++ b/Help/prop_tgt/CXX_STANDARD.rst
@@ -37,6 +37,12 @@ Supported values are:
C++23
+``26``
+ .. versionadded:: 3.25
+
+ C++26. CMake 3.25 and later *recognize* ``26`` as a valid value,
+ no version has support for any compiler.
+
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
means that using:
diff --git a/Help/prop_tgt/EXPORT_NO_SYSTEM.rst b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst
new file mode 100644
index 000000000..61f0a8da1
--- /dev/null
+++ b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst
@@ -0,0 +1,11 @@
+EXPORT_NO_SYSTEM
+----------------
+
+.. versionadded:: 3.25
+
+Specifies that :command:`install(EXPORT)` and :command:`export` commands will
+generate an imported target with :prop_tgt:`SYSTEM` property `OFF`.
+
+See the :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property to set this
+behavior on the target *consuming* the include directories rather than the
+one *providing* them.
diff --git a/Help/prop_tgt/HIP_STANDARD.rst b/Help/prop_tgt/HIP_STANDARD.rst
index 0c767c629..9de873038 100644
--- a/Help/prop_tgt/HIP_STANDARD.rst
+++ b/Help/prop_tgt/HIP_STANDARD.rst
@@ -25,6 +25,12 @@ Supported values are:
``23``
HIP C++23
+``26``
+ .. versionadded:: 3.25
+
+ HIP C++26. CMake 3.25 and later *recognize* ``26`` as a valid value,
+ no version has support for any compiler.
+
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
means that using:
diff --git a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
index ee22d6f19..913d9f2f9 100644
--- a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
+++ b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
@@ -3,11 +3,21 @@ IMPORTED_NO_SYSTEM
.. versionadded:: 3.23
+.. deprecated:: 3.25
+
+ ``IMPORTED_NO_SYSTEM`` is deprecated. Set :prop_tgt:`SYSTEM` to `OFF`
+ instead if you don't want target's include directories to be ``SYSTEM``
+ when compiling consumers. Set :prop_tgt:`EXPORT_NO_SYSTEM` to `ON` instead
+ if you don't want the include directories of the imported target generated
+ by :command:`install(EXPORT)` and :command:`export` commands to be
+ ``SYSTEM`` when compiling consumers.
+
Specifies that an :ref:`Imported Target <Imported Targets>` is not
a ``SYSTEM`` library. This has the following effects:
* Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are not treated
- as ``SYSTEM`` include directories when compiling consumers, as they
+ as ``SYSTEM`` include directories when compiling consumers (regardless of
+ the value of the consumed target's :prop_tgt:`SYSTEM` property), as they
would be by default. Entries of
:prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not affected,
and will always be treated as ``SYSTEM`` include directories.
diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst
new file mode 100644
index 000000000..3fe6d9a53
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst
@@ -0,0 +1,18 @@
+INTERFACE_CXX_MODULE_HEADER_UNIT_SETS
+-------------------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PUBLIC`` C++ module header sets (i.e. all
+file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files listed in these
+C++ module header sets can be installed with :command:`install(TARGETS)` and
+exported with :command:`install(EXPORT)` and :command:`export`.
+
+C++ module header sets may be defined using the :command:`target_sources`
+command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``.
+
+See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS`.
diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst
new file mode 100644
index 000000000..c7ed46d69
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst
@@ -0,0 +1,18 @@
+INTERFACE_CXX_MODULE_SETS
+-------------------------
+
+.. versionadded:: 3.25
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PUBLIC`` C++ module sets (i.e. all file sets
+with the type ``CXX_MODULES``). Files listed in these C++ module sets can be
+installed with :command:`install(TARGETS)` and exported with
+:command:`install(EXPORT)` and :command:`export`.
+
+C++ module sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``CXX_MODULES``.
+
+See also :prop_tgt:`CXX_MODULE_SETS`.
diff --git a/Help/prop_tgt/LANG_CLANG_TIDY.rst b/Help/prop_tgt/LANG_CLANG_TIDY.rst
index af16d3c5b..31f1876e3 100644
--- a/Help/prop_tgt/LANG_CLANG_TIDY.rst
+++ b/Help/prop_tgt/LANG_CLANG_TIDY.rst
@@ -3,13 +3,25 @@
.. versionadded:: 3.6
-This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` or ``OBJCXX``.
+This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC``
+or ``OBJCXX``.
-Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command
-line for the ``clang-tidy`` tool. The :ref:`Makefile Generators`
+Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing
+a command line for the ``clang-tidy`` tool. The :ref:`Makefile Generators`
and the :generator:`Ninja` generator will run this tool along with the
compiler and report a warning if the tool reports any problems.
+The specified ``clang-tidy`` command line will be invoked with additional
+arguments specifying the source file and, after ``--``, the full compiler
+command line.
+
+.. versionchanged:: 3.25
+
+ If the specified ``clang-tidy`` command line includes the ``-p`` option,
+ it will be invoked without ``--`` and the full compiler command line.
+ ``clang-tidy`` will look up the source file in the specified compiler
+ commands database.
+
This property is initialized by the value of
the :variable:`CMAKE_<LANG>_CLANG_TIDY` variable if it is set
when a target is created.
diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
index cba8ac98c..2e039bd3a 100644
--- a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
+++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
@@ -14,3 +14,8 @@ its arguments to the tool. Some example tools are distcc and ccache.
This property is initialized by the value of
the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable if it is set
when a target is created.
+
+.. versionadded:: 3.25
+
+ The property value may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
new file mode 100644
index 000000000..7f19bc09f
--- /dev/null
+++ b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
@@ -0,0 +1,16 @@
+``Embedded``
+ Compile with ``-Z7`` or equivalent flag(s) to produce object files
+ with full symbolic debugging information.
+``ProgramDatabase``
+ Compile with ``-Zi`` or equivalent flag(s) to produce a program
+ database that contains all the symbolic debugging information.
+``EditAndContinue``
+ Compile with ``-ZI`` or equivalent flag(s) to produce a program
+ database that supports the Edit and Continue feature.
+
+The value is ignored on compilers not targeting the MSVC ABI, but an
+unsupported value will be rejected as an error when using a compiler
+targeting the MSVC ABI.
+
+The value may also be the empty string (``""``), in which case no debug
+information format flag will be added explicitly by CMake.
diff --git a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst
new file mode 100644
index 000000000..0c7845ce4
--- /dev/null
+++ b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst
@@ -0,0 +1,33 @@
+MSVC_DEBUG_INFORMATION_FORMAT
+-----------------------------
+
+.. versionadded:: 3.25
+
+Select debug information format when targeting the MSVC ABI.
+
+The allowed values are:
+
+.. include:: MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>` to
+support per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+ add_executable(foo foo.c)
+ set_property(TARGET foo PROPERTY
+ MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>")
+
+selects for the target ``foo`` the program database debug information format
+for the Debug configuration.
+
+If this property is not set, CMake selects a debug information format using
+the default value ``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if
+supported by the compiler, and otherwise
+``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``.
+
+.. note::
+
+ This property has effect only when policy :policy:`CMP0141` is set to ``NEW``
+ prior to the first :command:`project` or :command:`enable_language` command
+ that enables a language using a compiler targeting the MSVC ABI.
diff --git a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
index 6c6134197..5f8b82dec 100644
--- a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
+++ b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
@@ -11,8 +11,9 @@
Compile with ``-MDd`` or equivalent flag(s) to use a multi-threaded
dynamically-linked runtime library.
-The value is ignored on non-MSVC compilers but an unsupported value will
-be rejected as an error when using a compiler targeting the MSVC ABI.
+The value is ignored on compilers not targeting the MSVC ABI, but an
+unsupported value will be rejected as an error when using a compiler
+targeting the MSVC ABI.
The value may also be the empty string (``""``) in which case no runtime
library selection flag will be added explicitly by CMake. Note that with
diff --git a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst
index 9b978b28d..9f13d38a7 100644
--- a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst
+++ b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst
@@ -21,7 +21,9 @@ support per-configuration specification. For example, the code:
selects for the target ``foo`` a multi-threaded statically-linked runtime
library with or without debug information depending on the configuration.
-If this property is not set then CMake uses the default value
+The property is initialized from the value of the
+:variable:`CMAKE_MSVC_RUNTIME_LIBRARY` variable, if it is set.
+If the property is not set, then CMake uses the default value
``MultiThreaded$<$<CONFIG:Debug>:Debug>DLL`` to select a MSVC runtime library.
.. note::
diff --git a/Help/prop_tgt/OBJCXX_STANDARD.rst b/Help/prop_tgt/OBJCXX_STANDARD.rst
index 654e6877d..6ac82169c 100644
--- a/Help/prop_tgt/OBJCXX_STANDARD.rst
+++ b/Help/prop_tgt/OBJCXX_STANDARD.rst
@@ -31,6 +31,12 @@ Supported values are:
Objective C++23
+``26``
+ .. versionadded:: 3.25
+
+ Objective C++26. CMake 3.25 and later *recognize* ``26`` as a valid value,
+ no version has support for any compiler.
+
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
means that using:
diff --git a/Help/prop_tgt/SYSTEM.rst b/Help/prop_tgt/SYSTEM.rst
new file mode 100644
index 000000000..a26773802
--- /dev/null
+++ b/Help/prop_tgt/SYSTEM.rst
@@ -0,0 +1,22 @@
+SYSTEM
+------
+
+.. versionadded:: 3.25
+
+Specifies that a target is a ``SYSTEM`` library. This has the following
+effects:
+
+* Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are treated as
+ ``SYSTEM`` include directories when compiling consumers.
+ Entries of :prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not
+ affected, and will always be treated as ``SYSTEM`` include directories.
+
+For imported targets, this property defaults to true, which means
+that their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are treated
+as ``SYSTEM`` by default. If their ``SYSTEM`` property is false,
+then their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` will not be
+treated as ``SYSTEM``, regardless of the value of the
+:prop_tgt:`IMPORTED_NO_SYSTEM` property.
+
+This target property is initialized from the :prop_dir:`SYSTEM`
+directory property when the target is created.
diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst
index 58476d6e2..1e84c0085 100644
--- a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst
+++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst
@@ -9,5 +9,5 @@ The property value may use
This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio
project file.
-This property only works for Visual Studio 2010 and above;
+This property only works for Visual Studio 11 2012 and above;
it is ignored on other generators.
diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst
index 6c26601a8..e54e140b6 100644
--- a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst
+++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst
@@ -9,5 +9,5 @@ The property value may use
This is defined in ``<LocalDebuggerCommandArguments>`` in the Visual Studio
project file.
-This property only works for Visual Studio 2010 and above;
+This property only works for Visual Studio 11 2012 and above;
it is ignored on other generators.
diff --git a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst
index 2f59a8219..60bc2f076 100644
--- a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst
+++ b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst
@@ -9,5 +9,5 @@ The property value may use
This is defined in ``<LocalDebuggerEnvironment>`` in the Visual Studio
project file.
-This property only works for Visual Studio 2010 and above;
+This property only works for Visual Studio 11 2012 and above;
it is ignored on other generators.
diff --git a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
index c163abf92..f9ce7aa36 100644
--- a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
+++ b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
@@ -9,5 +9,5 @@ The property value may use
This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio
project file.
-This property only works for Visual Studio 2010 and above;
+This property only works for Visual Studio 11 2012 and above;
it is ignored on other generators.
diff --git a/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst
index 52122939f..8a85ba489 100644
--- a/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst
+++ b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst
@@ -12,7 +12,7 @@ If the property is unset, Visual Studio uses the first matching
than one ``Main()`` method is available in the current project, the property
becomes mandatory for building the project.
-This property only works for Visual Studio 2010 and above;
+This property only works for Visual Studio 11 2012 and above;
it is ignored on other generators.
.. code-block:: cmake
diff --git a/Help/prop_tgt/VS_KEYWORD.rst b/Help/prop_tgt/VS_KEYWORD.rst
index 6c2e0420e..221b986ac 100644
--- a/Help/prop_tgt/VS_KEYWORD.rst
+++ b/Help/prop_tgt/VS_KEYWORD.rst
@@ -7,4 +7,4 @@ Can be set to change the visual studio keyword, for example Qt
integration works better if this is set to Qt4VSv1.0.
Use the :prop_tgt:`VS_GLOBAL_KEYWORD` target property to set the
-keyword for Visual Studio 10 (2010) and newer.
+keyword for Visual Studio 11 (2012) and newer.
diff --git a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
index 8f46d2f26..fa3c5bcee 100644
--- a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
+++ b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
@@ -30,6 +30,9 @@ at target creation time.
- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP`
- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER`
- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP`
+- :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION`
+- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION`
+- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION`
- :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS`
The following target properties will be applied on the
@@ -41,4 +44,5 @@ The following target properties will be applied on the
- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE`
- :prop_tgt:`XCODE_SCHEME_ENVIRONMENT`
- :prop_tgt:`XCODE_SCHEME_EXECUTABLE`
+- :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE`
- :prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY`
diff --git a/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst
new file mode 100644
index 000000000..3b801c503
--- /dev/null
+++ b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst
@@ -0,0 +1,14 @@
+XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+--------------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Metal: API Validation`` in the Options section of
+the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION`
+if it is set when a target is created.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst
new file mode 100644
index 000000000..5358087d5
--- /dev/null
+++ b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst
@@ -0,0 +1,14 @@
+XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+-----------------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Metal: Shader Validation`` in the Options section of
+the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION`
+if it is set when a target is created.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst
new file mode 100644
index 000000000..964332200
--- /dev/null
+++ b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst
@@ -0,0 +1,13 @@
+XCODE_SCHEME_LAUNCH_CONFIGURATION
+---------------------------------
+
+.. versionadded:: 3.25
+
+Set the build configuration to run the target.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION`
+if it is set when a target is created.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst
new file mode 100644
index 000000000..df5ae07ef
--- /dev/null
+++ b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst
@@ -0,0 +1,22 @@
+XCODE_SCHEME_LAUNCH_MODE
+------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Launch`` in the Info section of the generated Xcode
+scheme.
+
+Possible values are:
+
+``AUTO``
+ Launch automatically. This is the default.
+
+``WAIT``
+ Wait for the executable to be launched.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` if it is set when a target is
+created.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/release/3.0.rst b/Help/release/3.0.rst
index 64491e310..e37c13094 100644
--- a/Help/release/3.0.rst
+++ b/Help/release/3.0.rst
@@ -11,7 +11,7 @@ Documentation Changes
=====================
* The CMake documentation has been converted to reStructuredText and
- now transforms via Sphinx (`<http://sphinx-doc.org>`__) into man and
+ now transforms via Sphinx (`<https://www.sphinx-doc.org>`__) into man and
html pages. This allows the documentation to be properly indexed
and to contain cross-references.
diff --git a/Help/release/3.11.rst b/Help/release/3.11.rst
index a80657d2d..957dd4f1f 100644
--- a/Help/release/3.11.rst
+++ b/Help/release/3.11.rst
@@ -174,7 +174,7 @@ Modules
to removal of the ``javah`` tool by `JEP 313`_.
.. _`FLAME`: https://github.com/flame
-.. _`JEP 313`: http://openjdk.java.net/jeps/313
+.. _`JEP 313`: https://openjdk.java.net/jeps/313
Autogen
-------
diff --git a/Help/release/3.12.rst b/Help/release/3.12.rst
index 481027ec7..dcdae1d1b 100644
--- a/Help/release/3.12.rst
+++ b/Help/release/3.12.rst
@@ -242,7 +242,7 @@ CPack
* A :cpack_gen:`CPack NuGet Generator` was was added with basic
support for `NuGet`_.
-.. _NuGet: https://docs.microsoft.com/en-us/nuget/what-is-nuget
+.. _NuGet: https://learn.microsoft.com/en-us/nuget/what-is-nuget
Other
-----
@@ -302,4 +302,4 @@ Other Changes
(and legacy ``swig_add_module`` command) now set the prefix of
Java modules to ``""`` for MINGW, MSYS, and CYGWIN environments.
-.. _`Fortran Submodules`: http://fortranwiki.org/fortran/show/Submodules
+.. _Fortran Submodules: https://fortranwiki.org/fortran/show/Submodules
diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst
index 42e95beec..40cac41d7 100644
--- a/Help/release/3.20.rst
+++ b/Help/release/3.20.rst
@@ -217,8 +217,8 @@ Autogen
CTest
-----
-* :manual:`ctest(1)` gained a ``--test-dir`` option to specify the directory
- in which to look for tests.
+* :manual:`ctest(1)` gained a :option:`--test-dir <ctest --test-dir>`
+ option to specify the directory in which to look for tests.
CPack
-----
@@ -263,7 +263,7 @@ CPack
:variable:`CPACK_NUGET_<compName>_PACKAGE_LANGUAGE` allow the locale
for a package to be specified, for example ``en_CA``.
-.. _Software Package Data Exchange: https://spdx.org/
+.. _Software Package Data Exchange: https://spdx.dev/
Deprecated and Removed Features
===============================
diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst
index 462d2be81..91c3768e6 100644
--- a/Help/release/3.21.rst
+++ b/Help/release/3.21.rst
@@ -49,15 +49,15 @@ Languages
Command-Line
------------
-* :manual:`cmake(1)` gained the ``--install-prefix <dir>``
+* :manual:`cmake(1)` gained the :option:`--install-prefix <cmake --install-prefix>`
command-line option to specify the location of the install prefix.
-* :manual:`cmake(1)` gained the ``--toolchain <path/to/file>``
+* :manual:`cmake(1)` gained the :option:`--toolchain <cmake --toolchain>`
command-line option to specify a toolchain file.
-* :manual:`cmake(1)` ``-E capabilities`` output, for some generators,
- may now contain a ``supportedPlatforms`` field listing platforms
- known to be supported in :variable:`CMAKE_GENERATOR_PLATFORM`.
+* :manual:`cmake(1)` :option:`-E capabilities <cmake-E capabilities>` output,
+ for some generators, may now contain a ``supportedPlatforms`` field listing
+ platforms known to be supported in :variable:`CMAKE_GENERATOR_PLATFORM`.
* Messages printed to a terminal now may be colored by message type.
@@ -208,8 +208,8 @@ CTest
:prop_test:`ATTACHED_FILES_ON_FAIL` test properties.
See :ref:`Additional Test Measurements` for more information.
-* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results
- to a JUnit XML file.
+* :manual:`ctest(1)` gained a :option:`--output-junit <ctest --output-junit>`
+ option to write test results to a JUnit XML file.
* The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option.
diff --git a/Help/release/3.23.rst b/Help/release/3.23.rst
index 47b1869ac..6376d77a5 100644
--- a/Help/release/3.23.rst
+++ b/Help/release/3.23.rst
@@ -43,19 +43,22 @@ Generators
Command-Line
------------
-* The :manual:`cmake(1)` ``--build`` command, when used with
+* The :manual:`cmake(1)` :option:`--build <cmake --build>` command, when used with
:ref:`Visual Studio Generators` on projects that set the
:prop_tgt:`VS_PACKAGE_REFERENCES` target property, now automatically
restores package references from NuGet. The cache variable
:variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` may be set to toggle this behavior
- in a build tree. Use the ``--resolve-package-references=<on|off|only>``
+ in a build tree. Use the
+ :option:`--resolve-package-references <cmake--build --resolve-package-references>`
command-line option to control the behavior on one invocation.
-* The :manual:`cmake(1)` command line tool gained a ``--debug-find-pkg=``
+* The :manual:`cmake(1)` command line tool gained a
+ :option:`--debug-find-pkg <cmake --debug-find-pkg>`
option to enable debug messages under specific :command:`find_package`
calls.
-* The :manual:`cmake(1)` command line tool gained a ``--debug-find-var=``
+* The :manual:`cmake(1)` command line tool gained a
+ :option:`--debug-find-var <cmake --debug-find-var>`
option to enable debug messages for ``find_*`` calls that use specific
result variables.
diff --git a/Help/release/3.24.rst b/Help/release/3.24.rst
index 9317e51ae..f484e1af1 100644
--- a/Help/release/3.24.rst
+++ b/Help/release/3.24.rst
@@ -34,25 +34,28 @@ Generators
Command-Line
------------
-* :manual:`cmake(1)` gained the ``--fresh`` command-line option to remove
- any existing ``CMakeCache.txt`` file and associated ``CMakeFiles/``
+* :manual:`cmake(1)` gained the :option:`--fresh <cmake --fresh>` command-line
+ option to remove any existing ``CMakeCache.txt`` file and associated ``CMakeFiles/``
directory, when configuring a build tree, thus starting a new configuration
as if the build tree were freshly created.
-* :manual:`cmake(1)` gained the ``--compile-no-warning-as-error`` command-line
- option which causes the effects of the :prop_tgt:`COMPILE_WARNING_AS_ERROR`
- target property and :variable:`CMAKE_COMPILE_WARNING_AS_ERROR` variable
- to be ignored.
+* :manual:`cmake(1)` gained the
+ :option:`--compile-no-warning-as-error <cmake --compile-no-warning-as-error>`
+ command-line option which causes the effects of the
+ :prop_tgt:`COMPILE_WARNING_AS_ERROR` target property and
+ :variable:`CMAKE_COMPILE_WARNING_AS_ERROR` variable to be ignored.
-* The :manual:`cmake(1)` ``--trace=json-v1`` trace format gained fields
- ``global_frame`` and ``line_end``.
+* The :manual:`cmake(1)` :option:`--trace=json-v1 <cmake --trace>` trace
+ format gained fields ``global_frame`` and ``line_end``.
-* The :manual:`cmake(1)` ``-E`` commands ``cat`` and ``env`` learned to respect
- a double dash (``--``) argument that acts as a delimiter indicating the end of
- options. Any following arguments are treated as operands/positional arguments,
- even if they begin with a dash ``-`` character.
+* The :manual:`cmake(1)` :option:`-E <cmake -E>` commands :option:`cat <cmake-E cat>`
+ and :option:`env <cmake-E env>` learned to respect a double dash
+ (:option:`-- <cmake-E_env -->`) argument that acts as a delimiter indicating
+ the end of options. Any following arguments are treated as operands/positional
+ arguments, even if they begin with a dash ``-`` character.
-* The :manual:`cmake(1)` ``-E tar`` command gained the ``--touch`` option
+* The :manual:`cmake(1)` :option:`-E tar <cmake-E tar>` command gained the
+ :option:`--touch <cmake-E_tar --touch>` option
to keep the current local timestamp instead of extracting file timestamps
from the archive.
@@ -289,9 +292,10 @@ Generator Expressions
CTest
-----
-* :manual:`ctest(1)` gained a ``--test-output-truncation`` option (and
- corresponding :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variable) to
- specify the truncation mode once the maximum test output size has been
+* :manual:`ctest(1)` gained a
+ :option:`--test-output-truncation <ctest --test-output-truncation>` option
+ (and corresponding :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variable)
+ to specify the truncation mode once the maximum test output size has been
reached. Possible values are ``tail`` (default), ``middle`` or ``head``.
CPack
diff --git a/Help/release/3.25.rst b/Help/release/3.25.rst
new file mode 100644
index 000000000..7d0cf0a44
--- /dev/null
+++ b/Help/release/3.25.rst
@@ -0,0 +1,240 @@
+CMake 3.25 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.24 include the following.
+
+New Features
+============
+
+Presets
+-------
+
+* The :manual:`cmake-presets(7)` schema version has been bumped to ``6``.
+
+* The :manual:`cmake-presets(7)` format now supports a
+ ``packagePresets`` field to specify presets for :option:`cpack --preset`.
+
+* The :manual:`cmake-presets(7)` format now supports a
+ ``workflowPresets`` field to specify presets for :option:`cmake --workflow`.
+
+* The :manual:`cmake-presets(7)` format now supports an
+ ``outputJUnitFile`` field to specify JUnit output in test presets.
+
+Languages
+---------
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+ is now aware of C++26, and defines a ``cxx_std_26`` meta-feature.
+ C++26 compiler modes may also be specified via the :prop_tgt:`CXX_STANDARD`,
+ :prop_tgt:`CUDA_STANDARD`, :prop_tgt:`HIP_STANDARD`,
+ or :prop_tgt:`OBJCXX_STANDARD` target properties.
+
+* ``CUDA`` language support now includes device link-time optimization when
+ using ``nvcc``. The :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable
+ and the associated :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property
+ will activate device LTO.
+
+Command-Line
+------------
+
+* A :option:`cmake --workflow --preset <cmake--workflow --preset>` mode was
+ added to drive sequences of configure, build, test, and package operations
+ through a single command.
+
+* The :option:`cmake -E capabilities <cmake-E capabilities>` command
+ gained a new ``tls`` field that tells whether or not TLS is enabled.
+
+* The :option:`cmake -E env <cmake-E env>` command-line tool gained
+ a ``--modify`` flag to support :prop_test:`ENVIRONMENT_MODIFICATION`
+ operations.
+
+* The :option:`cmake --debug-trycompile` option now prints log messages
+ reporting the directory in which each try-compile check is done.
+
+Compilers
+---------
+
+* Support for the `Tasking compiler toolsets`_ (SmartCode, TriCore,
+ Standalone: ARM, MCS, 8051) was added with compiler id ``Tasking``.
+ See the :variable:`CMAKE_TASKING_TOOLSET` variable.
+
+.. _Tasking compiler toolsets: https://www.tasking.com
+
+Commands
+--------
+
+* The :command:`add_subdirectory` command gained a ``SYSTEM`` option
+ to enable the :prop_dir:`SYSTEM` directory property in the subdirectory.
+
+* The :command:`block` and :command:`endblock` commands were added to manage
+ specific scopes (policy or variable) for a contained block of commands.
+
+* The :command:`cmake_language` command gained a new
+ ``GET_MESSAGE_LOG_LEVEL`` sub-command. It can be used to
+ query the current message logging level.
+
+* The :command:`find_file`, :command:`find_path`, :command:`find_library`, and
+ :command:`find_program` commands gained a ``VALIDATOR`` option to specify a
+ function to be called for each candidate item to validate it.
+
+* The :command:`find_package` command now considers paths of
+ the form ``<prefix>/<name>*/(cmake|CMake)/<name>*/`` when
+ searching for package configuration files.
+
+* The :command:`return` command gained a ``PROPAGATE`` option to propagate
+ variables to the scope to which control returns.
+ See policy :policy:`CMP0140`.
+
+* The :command:`try_compile` and :command:`try_run` commands gained new
+ signatures that more consistently use keyword dispatch and do not require a
+ binary directory to be specified. Additionally, these signatures use a
+ unique directory for each invocation, which allows multiple outputs to be
+ preserved when using :option:`cmake --debug-trycompile`.
+
+* The :command:`try_compile` and :command:`try_run` commands gained the
+ option ``NO_CACHE`` to store results in normal variables.
+
+* The :command:`try_run` command gained ``RUN_OUTPUT_STDOUT_VARIABLE``
+ and ``RUN_OUTPUT_STDERR_VARIABLE`` options to capture stdout and stderr
+ separately from the output of the compiled program.
+
+Variables
+---------
+
+* The :variable:`BSD` and :variable:`CMAKE_HOST_BSD` variables are now set
+ to a string value when the target or host system is BSD, respectively.
+
+* The :variable:`LINUX` and :variable:`CMAKE_HOST_LINUX` variables are
+ now set to true when the target or host system is Linux, respectively.
+
+* The :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` variable and
+ :prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` target property were introduced
+ to select the debug information format for compilers targeting the MSVC ABI.
+ See policy :policy:`CMP0141`.
+
+* The :variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` variable and
+ corresponding :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` target
+ property were added to tell the :generator:`Xcode` generator what to put
+ in the scheme's ``Metal: API Validation`` setting.
+
+* The :variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` variable and
+ corresponding :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` target
+ property were added to tell the :generator:`Xcode` generator what to put
+ in the scheme's ``Metal: Shader Validation`` setting.
+
+* The :variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` variable and corresponding
+ :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` target property were added to tell
+ the :generator:`Xcode` generator what to put in the scheme's "Launch"
+ mode setting.
+
+* The :variable:`CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION` variable and
+ corresponding :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION` target
+ property were added to tell the :generator:`Xcode` generator what
+ configuration to put in the scheme's Launch action.
+
+Properties
+----------
+
+* The :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property now supports
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+* The :prop_tgt:`EXPORT_NO_SYSTEM` target property was added to
+ specify that :command:`install(EXPORT)` and :command:`export`
+ commands will generate na imported target with
+ :prop_tgt:`SYSTEM` property ``OFF``.
+
+* The :prop_tgt:`SYSTEM` target property was added to specify
+ whether a target should be treated as a system library (i.e.
+ its include directories are automatically ``SYSTEM`` when
+ compiling consumers). If not set, the default is the previous
+ behavior: on for imported targets and off for other targets.
+
+* The :prop_dir:`SYSTEM` directory property was added to initialize the
+ :prop_tgt:`SYSTEM` target property for targets created in that directory.
+
+Modules
+-------
+
+* The :module:`FetchContent` module :command:`FetchContent_Declare`
+ command gained a ``SYSTEM`` option to enable the :prop_dir:`SYSTEM`
+ directory property in the subdirectory.
+
+* The :module:`FindCUDAToolkit` module now provides a target for
+ :ref:`nvtx3 <cuda_toolkit_nvtx3>` for CUDA 10.0+, which supersedes
+ :ref:`nvToolsExt <cuda_toolkit_nvToolsExt>`. A deprecation warning
+ is emitted when using ``nvToolsExt`` if the project requires CMake
+ 3.25 and CUDA 10.0+ is used.
+
+* The :module:`FindDoxygen` module's version handling has been improved:
+
+ * Multiple candidate installations will now be considered, if needed,
+ to satisfy version constraints. Previously, only the first one
+ encountered would be considered.
+
+ * Version ranges are supported.
+
+ * Variations in the version format reported by Doxygen are now
+ tolerated (e.g. a trailing git commit hash).
+
+* The :module:`FindOpenAL` module now provides an imported target.
+
+* The :module:`FindOpenSP` module was added to find the OpenSP library.
+
+* The :module:`FindVulkan` module gained support for new components:
+
+ ``dxc``
+ DirectX Shader Compiler.
+
+ ``volk``
+ Volk open-source vulkan meta-loader.
+
+CPack
+-----
+
+* The :cpack_gen:`CPack Archive Generator` gained a new
+ :variable:`CPACK_ARCHIVE_FILE_EXTENSION` variable to control
+ the package file name extension.
+
+* The :cpack_gen:`CPack NSIS Generator` gained two new variables
+ :variable:`CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS` and
+ :variable:`CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS`
+ to provide arguments to the nsis executable invocation.
+
+* The :module:`CPack` module gained the :variable:`CPACK_READELF_EXECUTABLE`,
+ :variable:`CPACK_OBJCOPY_EXECUTABLE`, and
+ :variable:`CPACK_OBJDUMP_EXECUTABLE` variables to control the locations
+ of binutils used by :manual:`cpack(1)`.
+
+Deprecated and Removed Features
+===============================
+
+* The :prop_tgt:`IMPORTED_NO_SYSTEM` target property has been deprecated
+ in favor of :prop_tgt:`SYSTEM` and :prop_tgt:`EXPORT_NO_SYSTEM`.
+
+* The :generator:`Visual Studio 10 2010` generator has been removed.
+
+* The :generator:`Visual Studio 11 2012` generator is now deprecated
+ and will be removed in a future version of CMake.
+
+Other Changes
+=============
+
+* On Windows, when targeting the MSVC ABI, the :command:`find_library` command
+ now accepts ``.a`` file names after first considering ``.lib``. This is
+ symmetric with existing behavior when targeting the GNU ABI, in which the
+ command accepts ``.lib`` file names after first considering ``.a``.
+
+* The :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_DIR` environment
+ variables can now be used to override where to find certificate
+ authorities for TLS/SSL operations.
+
+* If :prop_tgt:`<LANG>_CLANG_TIDY` includes a ``-p`` argument, the
+ full compiler command line is no longer appended after ``--``.
+
+* The :generator:`Xcode` generator no longer adds the per-config suffix
+ ``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)`` to library search paths.
+ See policy :policy:`CMP0142`.
diff --git a/Help/release/3.3.rst b/Help/release/3.3.rst
index 44f4e19a1..2dc237f55 100644
--- a/Help/release/3.3.rst
+++ b/Help/release/3.3.rst
@@ -26,7 +26,7 @@ Generators
added on Windows. `Green Hills MULTI`_ is an IDE for embedded
real-time systems.
-.. _`Green Hills MULTI`: http://www.ghs.com/products/MULTI_IDE.html
+.. _`Green Hills MULTI`: https://www.ghs.com/products/MULTI_IDE.html
Commands
--------
diff --git a/Help/release/3.4.rst b/Help/release/3.4.rst
index 943d26716..abfede6ca 100644
--- a/Help/release/3.4.rst
+++ b/Help/release/3.4.rst
@@ -227,7 +227,7 @@ Other
will be merged with linker-generated manifests and embedded in the
binary.
-* The `Concurrent Fortran 77 <https://ccur.com>`__ compiler is now supported.
+* The Concurrent Fortran 77 compiler is now supported.
Its :variable:`compiler id <CMAKE_<LANG>_COMPILER_ID>` is ``CCur``.
* :manual:`cmake(1)` gained a new ``--trace-expand`` command line option
diff --git a/Help/release/3.7.rst b/Help/release/3.7.rst
index 345c056df..9656a546b 100644
--- a/Help/release/3.7.rst
+++ b/Help/release/3.7.rst
@@ -315,5 +315,5 @@ Other Changes
* Vim support files ``indent/cmake.vim`` and ``syntax/cmake.vim``
from the `vim-cmake-syntax`_ project are now distributed with CMake.
-.. _`Fortran Submodules`: http://fortranwiki.org/fortran/show/Submodules
+.. _`Fortran Submodules`: https://fortranwiki.org/fortran/show/Submodules
.. _`vim-cmake-syntax`: https://github.com/pboettch/vim-cmake-syntax
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 4dfac8a89..b6ecf7b09 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -13,6 +13,7 @@ Releases
.. toctree::
:maxdepth: 1
+ 3.25 <3.25>
3.24 <3.24>
3.23 <3.23>
3.22 <3.22>
diff --git a/Help/variable/BSD.rst b/Help/variable/BSD.rst
new file mode 100644
index 000000000..fdfe5ec98
--- /dev/null
+++ b/Help/variable/BSD.rst
@@ -0,0 +1,7 @@
+BSD
+---
+
+.. versionadded:: 3.25
+
+Set to a string value when the target system is BSD. This value can be one of
+the following: DragonFlyBSD, FreeBSD, OpenBSD, or NetBSD.
diff --git a/Help/variable/CMAKE_ANDROID_API.rst b/Help/variable/CMAKE_ANDROID_API.rst
index 4388bf2e0..aba9b6eb6 100644
--- a/Help/variable/CMAKE_ANDROID_API.rst
+++ b/Help/variable/CMAKE_ANDROID_API.rst
@@ -8,6 +8,7 @@ Edition`, this variable may be set to specify the default value for the
:prop_tgt:`ANDROID_API` target property. See that target property for
additional information.
-Otherwise, when :ref:`Cross Compiling for Android`, this variable provides
-the Android API version number targeted. This will be the same value as
-the :variable:`CMAKE_SYSTEM_VERSION` variable for ``Android`` platforms.
+When :ref:`Cross Compiling for Android`, the :variable:`CMAKE_SYSTEM_VERSION`
+variable represents the Android API version number targeted. For historical
+reasons, if a toolchain file sets ``CMAKE_ANDROID_API``, but not
+``CMAKE_SYSTEM_VERSION``, the latter will be initialized using the former.
diff --git a/Help/variable/CMAKE_BINARY_DIR.rst b/Help/variable/CMAKE_BINARY_DIR.rst
index 3b323b7ae..e601eb816 100644
--- a/Help/variable/CMAKE_BINARY_DIR.rst
+++ b/Help/variable/CMAKE_BINARY_DIR.rst
@@ -7,7 +7,7 @@ This is the full path to the top level of the current CMake build
tree. For an in-source build, this would be the same as
:variable:`CMAKE_SOURCE_DIR`.
-When run in -P script mode, CMake sets the variables
+When run in :option:`cmake -P` script mode, CMake sets the variables
:variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`,
:variable:`CMAKE_CURRENT_BINARY_DIR` and
:variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory.
diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst
index 43668eaac..3a57659c0 100644
--- a/Help/variable/CMAKE_CFG_INTDIR.rst
+++ b/Help/variable/CMAKE_CFG_INTDIR.rst
@@ -19,7 +19,7 @@ Example values:
::
$(ConfigurationName) = Visual Studio 9
- $(Configuration) = Visual Studio 10
+ $(Configuration) = Visual Studio 11 and above
$(CONFIGURATION) = Xcode
. = Make-based tools
. = Ninja
diff --git a/Help/variable/CMAKE_COMMAND.rst b/Help/variable/CMAKE_COMMAND.rst
index f80b46cb5..e65ff8c49 100644
--- a/Help/variable/CMAKE_COMMAND.rst
+++ b/Help/variable/CMAKE_COMMAND.rst
@@ -4,5 +4,5 @@ CMAKE_COMMAND
The full path to the :manual:`cmake(1)` executable.
This is the full path to the CMake executable :manual:`cmake(1)` which is
-useful from custom commands that want to use the ``cmake -E`` option for
+useful from custom commands that want to use the :option:`cmake -E` option for
portable system commands. (e.g. ``/usr/local/bin/cmake``)
diff --git a/Help/variable/CMAKE_CPACK_COMMAND.rst b/Help/variable/CMAKE_CPACK_COMMAND.rst
index 3a81d6816..f851a183d 100644
--- a/Help/variable/CMAKE_CPACK_COMMAND.rst
+++ b/Help/variable/CMAKE_CPACK_COMMAND.rst
@@ -5,6 +5,6 @@ CMAKE_CPACK_COMMAND
Full path to :manual:`cpack(1)` command installed with CMake.
-This is the full path to the CPack executable :manual:`cpack(1)` which is
-useful from custom commands that want to use the :manual:`cmake(1)` ``-E``
-option for portable system commands.
+This is the full path to the CPack executable :manual:`cpack(1)`
+that can be used for custom commands or tests to invoke
+CPack commands.
diff --git a/Help/variable/CMAKE_CTEST_COMMAND.rst b/Help/variable/CMAKE_CTEST_COMMAND.rst
index b2942e2a8..a3b751f39 100644
--- a/Help/variable/CMAKE_CTEST_COMMAND.rst
+++ b/Help/variable/CMAKE_CTEST_COMMAND.rst
@@ -3,6 +3,6 @@ CMAKE_CTEST_COMMAND
Full path to :manual:`ctest(1)` command installed with CMake.
-This is the full path to the CTest executable :manual:`ctest(1)` which is
-useful from custom commands that want to use the :manual:`cmake(1)` ``-E``
-option for portable system commands.
+This is the full path to the CTest executable :manual:`ctest(1)`
+that can be used for custom commands or tests to invoke
+CTest commands.
diff --git a/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst b/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst
index 8fc85eed1..15f81d2cc 100644
--- a/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst
+++ b/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst
@@ -9,7 +9,7 @@ create a binary directory in the build tree, and as it is being
processed this variable will be set. For in-source builds this is the
current source directory being processed.
-When run in -P script mode, CMake sets the variables
+When run in :option:`cmake -P` script mode, CMake sets the variables
:variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`,
:variable:`CMAKE_CURRENT_BINARY_DIR` and
:variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory.
diff --git a/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst b/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst
index 1a25efca8..5b860268a 100644
--- a/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst
+++ b/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst
@@ -6,7 +6,7 @@ The path to the source directory currently being processed.
This is the full path to the source directory that is currently being
processed by cmake.
-When run in -P script mode, CMake sets the variables
+When run in :option:`cmake -P` script mode, CMake sets the variables
:variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`,
:variable:`CMAKE_CURRENT_BINARY_DIR` and
:variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory.
diff --git a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
index f77e93916..58818f40f 100644
--- a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
+++ b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
@@ -13,6 +13,6 @@ This switch should be used during the initial CMake run. Otherwise if
the package has already been found in a previous CMake run, the
variables which have been stored in the cache will still be there. In
that case it is recommended to remove the cache variables for this
-package from the cache using the cache editor or :manual:`cmake(1)` ``-U``
+package from the cache using the cache editor or :option:`cmake -U`.
See also the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable.
diff --git a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
index 53a19dca4..a7e9029dc 100644
--- a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
+++ b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
@@ -33,7 +33,7 @@ property for all targets.
.. note::
This option is implemented only by :ref:`Makefile Generators`
- and the :generator:`Ninja`. It is ignored on other generators.
+ and :ref:`Ninja Generators`. It is ignored on other generators.
This option currently does not work well in combination with
the :prop_tgt:`UNITY_BUILD` target property or the
diff --git a/Help/variable/CMAKE_FIND_DEBUG_MODE.rst b/Help/variable/CMAKE_FIND_DEBUG_MODE.rst
index 8f2a82f24..48b0dce65 100644
--- a/Help/variable/CMAKE_FIND_DEBUG_MODE.rst
+++ b/Help/variable/CMAKE_FIND_DEBUG_MODE.rst
@@ -13,7 +13,7 @@ error:
* :command:`find_package`
Output is designed for human consumption and not for parsing.
-Enabling this variable is equivalent to using :manual:`cmake <cmake(1)>` ``--debug-find``
+Enabling this variable is equivalent to using :option:`cmake --debug-find`
with the added ability to enable debugging for a subset of find calls.
.. code-block:: cmake
diff --git a/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst
index 5d45fb0b6..b27a3d95a 100644
--- a/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst
+++ b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst
@@ -25,4 +25,4 @@ CMake configures the project.
``CMAKE_FIND_PACKAGE_REDIRECTS_DIR`` is only set in CMake project mode.
It is not set when CMake is run in script mode
-(i.e. :manual:`cmake -P ... <cmake(1)>`).
+(i.e. :option:`cmake -P`).
diff --git a/Help/variable/CMAKE_GENERATOR.rst b/Help/variable/CMAKE_GENERATOR.rst
index ec52cd4d8..0e249eb51 100644
--- a/Help/variable/CMAKE_GENERATOR.rst
+++ b/Help/variable/CMAKE_GENERATOR.rst
@@ -7,6 +7,6 @@ The name of the generator that is being used to generate the build
files. (e.g. ``Unix Makefiles``, ``Ninja``, etc.)
The value of this variable should never be modified by project code.
-A generator may be selected via the :manual:`cmake(1)` ``-G`` option,
+A generator may be selected via the :option:`cmake -G` option,
interactively in :manual:`cmake-gui(1)`, or via the :envvar:`CMAKE_GENERATOR`
environment variable.
diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
index b17d83acf..acb7b2e1a 100644
--- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
+++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
@@ -7,7 +7,7 @@ Generator-specific target platform specification provided by user.
Some CMake generators support a target platform name to be given
to the native build system to choose a compiler toolchain.
-If the user specifies a platform name (e.g. via the :manual:`cmake(1)` ``-A``
+If the user specifies a platform name (e.g. via the :option:`cmake -A`
option or via the :envvar:`CMAKE_GENERATOR_PLATFORM` environment variable)
the value will be available in this variable.
diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
index 45f2d3236..485547784 100644
--- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
+++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
@@ -5,7 +5,7 @@ Native build system toolset specification provided by user.
Some CMake generators support a toolset specification to tell the
native build system how to choose a compiler. If the user specifies
-a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option or via
+a toolset (e.g. via the :option:`cmake -T` option or via
the :envvar:`CMAKE_GENERATOR_TOOLSET` environment variable) the value
will be available in this variable.
diff --git a/Help/variable/CMAKE_HOST_BSD.rst b/Help/variable/CMAKE_HOST_BSD.rst
new file mode 100644
index 000000000..d3554f94f
--- /dev/null
+++ b/Help/variable/CMAKE_HOST_BSD.rst
@@ -0,0 +1,7 @@
+CMAKE_HOST_BSD
+--------------
+
+.. versionadded:: 3.25
+
+Set to a string value when the host system is BSD. This value can be one of
+the following: DragonFlyBSD, FreeBSD, OpenBSD, or NetBSD.
diff --git a/Help/variable/CMAKE_HOST_LINUX.rst b/Help/variable/CMAKE_HOST_LINUX.rst
new file mode 100644
index 000000000..e2361bd05
--- /dev/null
+++ b/Help/variable/CMAKE_HOST_LINUX.rst
@@ -0,0 +1,6 @@
+CMAKE_HOST_LINUX
+----------------
+
+.. versionadded:: 3.25
+
+Set to true when the host system is Linux.
diff --git a/Help/variable/CMAKE_INSTALL_PREFIX.rst b/Help/variable/CMAKE_INSTALL_PREFIX.rst
index 6d42ea8f0..c76727e76 100644
--- a/Help/variable/CMAKE_INSTALL_PREFIX.rst
+++ b/Help/variable/CMAKE_INSTALL_PREFIX.rst
@@ -27,8 +27,9 @@ first :command:`project` invocation.
The ``CMAKE_INSTALL_PREFIX`` may be defined when configuring a build tree
to set its installation prefix. Or, when using the :manual:`cmake(1)`
-command-line tool's ``--install`` mode, one may specify a different prefix
-using the ``--prefix`` option:
+command-line tool's :option:`--install <cmake --install>` mode, one may specify
+a different prefix using the :option:`--prefix <cmake--install --prefix>`
+option:
.. code-block:: shell
diff --git a/Help/variable/CMAKE_LANG_COMPILER.rst b/Help/variable/CMAKE_LANG_COMPILER.rst
index e694b337e..db8f4e1fa 100644
--- a/Help/variable/CMAKE_LANG_COMPILER.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER.rst
@@ -14,7 +14,8 @@ This variable can be set by the user during the first time a build tree is confi
If a non-full path value is supplied then CMake will resolve the full path of
the compiler.
-The variable could be set in a user supplied toolchain file or via `-D` on the command line.
+The variable could be set in a user supplied toolchain file or via
+:option:`-D <cmake -D>` on the command line.
.. note::
Options that are required to make the compiler work correctly can be included
diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
index 6a0a1d9cd..e311d1bdd 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
@@ -6,43 +6,62 @@ Compiler identification string.
A short string unique to the compiler vendor. Possible values
include:
-::
-
- Absoft = Absoft Fortran (absoft.com)
- ADSP = Analog VisualDSP++ (analog.com)
- AppleClang = Apple Clang (apple.com)
- ARMCC = ARM Compiler (arm.com)
- ARMClang = ARM Compiler based on Clang (arm.com)
- Bruce = Bruce C Compiler
- CCur = Concurrent Fortran (ccur.com)
- Clang = LLVM Clang (clang.llvm.org)
- Cray = Cray Compiler (cray.com)
- Embarcadero, Borland = Embarcadero (embarcadero.com)
- Flang = Classic Flang Fortran Compiler (https://github.com/flang-compiler/flang)
- LLVMFlang = LLVM Flang Fortran Compiler (https://github.com/llvm/llvm-project/tree/main/flang)
- Fujitsu = Fujitsu HPC compiler (Trad mode)
- FujitsuClang = Fujitsu HPC compiler (Clang mode)
- G95 = G95 Fortran (g95.org)
- GNU = GNU Compiler Collection (gcc.gnu.org)
- GHS = Green Hills Software (www.ghs.com)
- HP = Hewlett-Packard Compiler (hp.com)
- IAR = IAR Systems (iar.com)
- Intel = Intel Compiler (intel.com)
- IntelLLVM = Intel LLVM-Based Compiler (intel.com)
- LCC = MCST Elbrus C/C++/Fortran Compiler (mcst.ru)
- MSVC = Microsoft Visual Studio (microsoft.com)
- NVHPC = NVIDIA HPC SDK Compiler (nvidia.com)
- NVIDIA = NVIDIA CUDA Compiler (nvidia.com)
- OpenWatcom = Open Watcom (openwatcom.org)
- PGI = The Portland Group (pgroup.com)
- PathScale = PathScale (pathscale.com)
- SDCC = Small Device C Compiler (sdcc.sourceforge.net)
- SunPro = Oracle Solaris Studio (oracle.com)
- TI = Texas Instruments (ti.com)
- TinyCC = Tiny C Compiler (tinycc.org)
- XL, VisualAge, zOS = IBM XL (ibm.com)
- XLClang = IBM Clang-based XL (ibm.com)
- IBMClang = IBM LLVM-based Compiler (ibm.com)
+=============================== ===============================================
+Value Name
+=============================== ===============================================
+``Absoft`` `Absoft Fortran`_
+``ADSP`` Analog VisualDSP++
+``AppleClang`` Apple Clang
+``ARMCC`` ARM Compiler
+``ARMClang`` ARM Compiler based on Clang
+``Bruce`` Bruce C Compiler
+``CCur`` Concurrent Fortran
+``Clang`` `LLVM Clang`_
+``Cray`` Cray Compiler
+``Embarcadero``, ``Borland`` `Embarcadero`_
+``Flang`` `Classic Flang Fortran Compiler`_
+``LLVMFlang`` `LLVM Flang Fortran Compiler`_
+``Fujitsu`` Fujitsu HPC compiler (Trad mode)
+``FujitsuClang`` Fujitsu HPC compiler (Clang mode)
+``G95`` `G95 Fortran`_
+``GNU`` `GNU Compiler Collection`_
+``GHS`` `Green Hills Software`_
+``HP`` Hewlett-Packard Compiler
+``IAR`` IAR Systems
+``Intel`` Intel Compiler
+``IntelLLVM`` Intel LLVM-Based Compiler
+``LCC`` MCST Elbrus C/C++/Fortran Compiler
+``MSVC`` `Microsoft Visual Studio`_
+``NVHPC`` `NVIDIA HPC Compiler`_
+``NVIDIA`` `NVIDIA CUDA Compiler`_
+``OpenWatcom`` `Open Watcom`_
+``PGI`` The Portland Group
+``PathScale`` PathScale
+``SDCC`` `Small Device C Compiler`_
+``SunPro`` Oracle Solaris Studio
+``Tasking`` `Tasking Compiler Toolsets`_
+``TI`` Texas Instruments
+``TinyCC`` `Tiny C Compiler`_
+``XL``, ``VisualAge``, ``zOS`` IBM XL
+``XLClang`` IBM Clang-based XL
+``IBMClang`` IBM LLVM-based Compiler
+=============================== ===============================================
This variable is not guaranteed to be defined for all compilers or
languages.
+
+.. _Absoft Fortran: https://www.absoft.com
+.. _LLVM Clang: https://clang.llvm.org
+.. _Embarcadero: https://www.embarcadero.com
+.. _Classic Flang Fortran Compiler: https://github.com/flang-compiler/flang
+.. _LLVM Flang Fortran Compiler: https://github.com/llvm/llvm-project/tree/main/flang
+.. _G95 Fortran: https://g95.sourceforge.net
+.. _GNU Compiler Collection: https://gcc.gnu.org
+.. _Green Hills Software: https://www.ghs.com/products/compiler.html
+.. _Microsoft Visual Studio: https://visualstudio.microsoft.com
+.. _NVIDIA HPC Compiler: https://developer.nvidia.com/hpc-compilers
+.. _NVIDIA CUDA Compiler: https://developer.nvidia.com/cuda-llvm-compiler
+.. _Open Watcom: https://open-watcom.github.io
+.. _Small Device C Compiler: https://sdcc.sourceforge.net
+.. _Tiny C Compiler: https://bellard.org/tcc
+.. _Tasking Compiler Toolsets: https://www.tasking.com
diff --git a/Help/variable/CMAKE_LANG_FLAGS.rst b/Help/variable/CMAKE_LANG_FLAGS.rst
index 2784397ac..4b39b1def 100644
--- a/Help/variable/CMAKE_LANG_FLAGS.rst
+++ b/Help/variable/CMAKE_LANG_FLAGS.rst
@@ -5,7 +5,9 @@ Flags for all build types.
``<LANG>`` flags used regardless of the value of :variable:`CMAKE_BUILD_TYPE`.
-This is initialized for each language from environment variables:
+For each language, if this variable is not defined, it is initialized
+and stored in the cache using values from environment variables in
+combination with CMake's builtin defaults for the toolchain:
* ``CMAKE_C_FLAGS``:
Initialized by the :envvar:`CFLAGS` environment variable.
@@ -15,6 +17,12 @@ This is initialized for each language from environment variables:
Initialized by the :envvar:`CUDAFLAGS` environment variable.
* ``CMAKE_Fortran_FLAGS``:
Initialized by the :envvar:`FFLAGS` environment variable.
+* ``CMAKE_CSharp_FLAGS``:
+ Initialized by the :envvar:`CSFLAGS` environment variable.
+* ``CMAKE_HIP_FLAGS``:
+ Initialized by the :envvar:`HIPFLAGS` environment variable.
+* ``CMAKE_ISPC_FLAGS``:
+ Initialized by the :envvar:`ISPCFLAGS` environment variable.
This value is a command-line string fragment. Therefore, multiple options
should be separated by spaces, and options with spaces should be quoted.
diff --git a/Help/variable/CMAKE_MAKE_PROGRAM.rst b/Help/variable/CMAKE_MAKE_PROGRAM.rst
index a3c8b7c8a..9769c7ae7 100644
--- a/Help/variable/CMAKE_MAKE_PROGRAM.rst
+++ b/Help/variable/CMAKE_MAKE_PROGRAM.rst
@@ -59,6 +59,6 @@ to configure the project:
variable, changing the value has undefined behavior.
The ``CMAKE_MAKE_PROGRAM`` variable is set for use by project code.
-The value is also used by the :manual:`cmake(1)` ``--build`` and
-:manual:`ctest(1)` ``--build-and-test`` tools to launch the native
+The value is also used by the :option:`cmake --build` and
+:option:`ctest --build-and-test` tools to launch the native
build process.
diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst
index 41ace436f..7274b7b68 100644
--- a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst
+++ b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst
@@ -3,7 +3,7 @@ CMAKE_MESSAGE_CONTEXT
.. versionadded:: 3.17
-When enabled by the :manual:`cmake <cmake(1)>` ``--log-context`` command line
+When enabled by the :option:`cmake --log-context` command line
option or the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable, the
:command:`message` command converts the ``CMAKE_MESSAGE_CONTEXT`` list into a
dot-separated string surrounded by square brackets and prepends it to each line
diff --git a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
index 3b45d1ddf..4539c90ac 100644
--- a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
+++ b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
@@ -5,8 +5,9 @@ CMAKE_MESSAGE_LOG_LEVEL
When set, this variable specifies the logging level used by the
:command:`message` command. Valid values are the same as those for the
-``--log-level`` command line option of the :manual:`cmake(1)` program.
-If this variable is set and the ``--log-level`` command line option is
+:option:`--log-level <cmake --log-level>` command line option of the
+:manual:`cmake(1)` program. If this variable is set and the
+:option:`--log-level <cmake --log-level>` command line option is
given, the command line option takes precedence.
The main advantage to using this variable is to make a log level persist
@@ -15,3 +16,8 @@ subsequent CMake runs will continue to use the chosen log level.
Projects should not set this variable, it is intended for users so that
they may control the log level according to their own needs.
+
+.. versionadded:: 3.25
+ See the :command:`cmake_language`
+ :ref:`cmake_language <query_message_log_level>` command for a way to query
+ the current message logging level.
diff --git a/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst b/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst
new file mode 100644
index 000000000..80df8fc1f
--- /dev/null
+++ b/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst
@@ -0,0 +1,36 @@
+CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
+-----------------------------------
+
+.. versionadded:: 3.25
+
+Select the MSVC debug information format targeting the MSVC ABI.
+This variable is used to initialize the
+:prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` property on all targets as they are
+created. It is also propagated by calls to the :command:`try_compile` command
+into the test project.
+
+The allowed values are:
+
+.. include:: ../prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>` to
+support per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>")
+
+selects for all following targets the program database debug information format
+for the Debug configuration.
+
+If this variable is not set, the :prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT`
+target property will not be set automatically. If that property is not set,
+CMake selects a debug information format using the default value
+``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if supported by the
+compiler, and otherwise ``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``.
+
+.. note::
+
+ This variable has effect only when policy :policy:`CMP0141` is set to ``NEW``
+ prior to the first :command:`project` or :command:`enable_language` command
+ that enables a language using a compiler targeting the MSVC ABI.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index 9dce7600a..f844105e4 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -42,5 +42,8 @@ only for the policies that do not warn by default:
This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to
enable the warning (e.g. ``-DCMAKE_POLICY_WARNING_CMP<NNNN>=ON``).
-Alternatively, running :manual:`cmake(1)` with the ``--debug-output``,
-``--trace``, or ``--trace-expand`` option will also enable the warning.
+Alternatively, running :manual:`cmake(1)` with the
+:option:`--debug-output <cmake --debug-output>`,
+:option:`--trace <cmake --trace>`, or
+:option:`--trace-expand <cmake --trace-expand>` option will also
+enable the warning.
diff --git a/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst b/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst
index 981af60cf..313fb4eb6 100644
--- a/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst
+++ b/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst
@@ -1,9 +1,9 @@
CMAKE_SCRIPT_MODE_FILE
----------------------
-Full path to the :manual:`cmake(1)` ``-P`` script file currently being
+Full path to the :option:`cmake -P` script file currently being
processed.
-When run in :manual:`cmake(1)` ``-P`` script mode, CMake sets this variable to
+When run in :option:`cmake -P` script mode, CMake sets this variable to
the full path of the script file. When run to configure a ``CMakeLists.txt``
file, this variable is not set.
diff --git a/Help/variable/CMAKE_SOURCE_DIR.rst b/Help/variable/CMAKE_SOURCE_DIR.rst
index d1f179838..7210f75c5 100644
--- a/Help/variable/CMAKE_SOURCE_DIR.rst
+++ b/Help/variable/CMAKE_SOURCE_DIR.rst
@@ -7,7 +7,7 @@ This is the full path to the top level of the current CMake source
tree. For an in-source build, this would be the same as
:variable:`CMAKE_BINARY_DIR`.
-When run in ``-P`` script mode, CMake sets the variables
+When run in :option:`cmake -P` script mode, CMake sets the variables
:variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`,
:variable:`CMAKE_CURRENT_BINARY_DIR` and
:variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory.
diff --git a/Help/variable/CMAKE_TASKING_TOOLSET.rst b/Help/variable/CMAKE_TASKING_TOOLSET.rst
new file mode 100644
index 000000000..6bd14798d
--- /dev/null
+++ b/Help/variable/CMAKE_TASKING_TOOLSET.rst
@@ -0,0 +1,34 @@
+CMAKE_TASKING_TOOLSET
+---------------------
+
+.. versionadded:: 3.25
+
+Select the Tasking toolset which provides the compiler
+
+Architecture compilers are provided by different toolchains with
+incompatible versioning schemes. Set this variable in a
+:variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` so CMake can detect
+the compiler features correctly. If no toolset is specified,
+``Standalone`` is assumed.
+
+Due to the different versioning schemes, the compiler version
+(:variable:`CMAKE_<LANG>_COMPILER_VERSION`) depends on the toolset and
+architecture in use. If projects can be built with multiple toolsets or
+architectures, the specified :variable:`CMAKE_TASKING_TOOLSET` and the
+automatically determined :variable:`CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID`
+must be taken into account when comparing against the
+:variable:`CMAKE_<LANG>_COMPILER_VERSION`.
+
+``TriCore``
+ Compilers are provided by the TriCore toolset.
+
+``SmartCode``
+ Compilers are provided by the SmartCode toolset.
+
+``Standalone``
+ Compilers are provided by the standalone toolsets.
+
+ .. note::
+
+ For the TriCore architecture, the compiler from the TriCore toolset is
+ selected as standalone compiler.
diff --git a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
index f109a9eda..2bb97c42d 100644
--- a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
+++ b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
@@ -10,5 +10,5 @@ This variable is not defined by other generators even if ``devenv.com``
is installed on the computer.
The :variable:`CMAKE_VS_MSBUILD_COMMAND` is also provided for
-:generator:`Visual Studio 10 2010` and above.
+:generator:`Visual Studio 11 2012` and above.
See also the :variable:`CMAKE_MAKE_PROGRAM` variable.
diff --git a/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst b/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst
index 58f2bef4c..8a521a3c8 100644
--- a/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst
+++ b/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst
@@ -1,7 +1,7 @@
CMAKE_VS_MSBUILD_COMMAND
------------------------
-The generators for :generator:`Visual Studio 10 2010` and above set this
+The generators for :generator:`Visual Studio 11 2012` and above set this
variable to the ``MSBuild.exe`` command installed with the corresponding
Visual Studio version.
diff --git a/Help/variable/CMAKE_WARN_DEPRECATED.rst b/Help/variable/CMAKE_WARN_DEPRECATED.rst
index 4a224fa5c..c7b615938 100644
--- a/Help/variable/CMAKE_WARN_DEPRECATED.rst
+++ b/Help/variable/CMAKE_WARN_DEPRECATED.rst
@@ -7,4 +7,5 @@ If not ``FALSE``, use of deprecated functionality will issue warnings.
If this variable is not set, CMake behaves as if it were set to ``TRUE``.
When running :manual:`cmake(1)`, this option can be enabled with the
-``-Wdeprecated`` option, or disabled with the ``-Wno-deprecated`` option.
+:option:`-Wdeprecated <cmake -Wdeprecated>` option, or disabled with the
+:option:`-Wno-deprecated <cmake -Wno-deprecated>` option.
diff --git a/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst b/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst
index 210da52d5..6d72d1414 100644
--- a/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst
+++ b/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst
@@ -5,5 +5,5 @@ Xcode compiler selection.
:generator:`Xcode` supports selection of a compiler from one of the installed
toolsets. CMake provides the name of the chosen toolset in this
-variable, if any is explicitly selected (e.g. via the :manual:`cmake(1)`
-``-T`` option).
+variable, if any is explicitly selected (e.g. via the :option:`cmake -T`
+option).
diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst
new file mode 100644
index 000000000..ce5c4b3fb
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst
@@ -0,0 +1,13 @@
+CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+--------------------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Metal: API Validation`` in the Options section of
+the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` property on all targets.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst
new file mode 100644
index 000000000..073a6c9af
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst
@@ -0,0 +1,13 @@
+CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+-----------------------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Metal: Shader Validation`` in the Options section of
+the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` property on all targets.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst
new file mode 100644
index 000000000..e5b4d1813
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst
@@ -0,0 +1,12 @@
+CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION
+---------------------------------------
+
+.. versionadded:: 3.25
+
+Set the build configuration to run the target.
+
+This variable initializes the :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION`
+property on all targets.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst
new file mode 100644
index 000000000..c15b1eada
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst
@@ -0,0 +1,13 @@
+CMAKE_XCODE_SCHEME_LAUNCH_MODE
+------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Launch`` in the Info section of the generated Xcode
+scheme.
+
+This variable initializes the :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` property on
+all targets.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst
index 1c070b8fa..9bd50db01 100644
--- a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst
+++ b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst
@@ -3,7 +3,7 @@ CPACK_CUSTOM_INSTALL_VARIABLES
.. versionadded:: 3.21
-CPack variables (set via e.g. ``cpack -D``, ``CPackConfig.cmake`` or
+CPack variables (set via e.g. :option:`cpack -D`, ``CPackConfig.cmake`` or
:variable:`CPACK_PROJECT_CONFIG_FILE` scripts) are not directly visible in
installation scripts. Instead, one can pass a list of ``varName=value``
pairs in the ``CPACK_CUSTOM_INSTALL_VARIABLES`` variable. At install time,
diff --git a/Help/variable/CTEST_CONFIGURATION_TYPE.rst b/Help/variable/CTEST_CONFIGURATION_TYPE.rst
index 392845e29..932f81d1e 100644
--- a/Help/variable/CTEST_CONFIGURATION_TYPE.rst
+++ b/Help/variable/CTEST_CONFIGURATION_TYPE.rst
@@ -6,5 +6,5 @@ CTEST_CONFIGURATION_TYPE
Specify the CTest ``DefaultCTestConfigurationType`` setting
in a :manual:`ctest(1)` dashboard client script.
-If the configuration type is set via ``-C <cfg>`` from the command line
+If the configuration type is set via :option:`-C \<cfg\> <ctest -C>` from the command line
then this variable is populated accordingly.
diff --git a/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst b/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst
index 32c85ad5c..8cb6eaaac 100644
--- a/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst
+++ b/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst
@@ -4,4 +4,4 @@ CTEST_RUN_CURRENT_SCRIPT
.. versionadded:: 3.11
Setting this to 0 prevents :manual:`ctest(1)` from being run again when it
-reaches the end of a script run by calling ``ctest -S``.
+reaches the end of a script run by calling :option:`ctest -S`.
diff --git a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
index 8ae6c57e4..aea1be8f6 100644
--- a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
+++ b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
@@ -45,8 +45,8 @@
wildcard, and optional parts are shown as ``[...]``):
* ``[/path/to/]FwName[.framework]``
- * ``[/path/to/]FwName.framework/FwName``
- * ``[/path/to/]FwName.framework/Versions/*/FwName``
+ * ``[/path/to/]FwName.framework/FwName[suffix]``
+ * ``[/path/to/]FwName.framework/Versions/*/FwName[suffix]``
Note that CMake recognizes and automatically handles framework targets,
even without using the ``$<LINK_LIBRARY:FRAMEWORK,...>`` expression.
@@ -59,6 +59,11 @@
``$<LINK_LIBRARY:FRAMEWORK,...>`` for file paths so that the expected
behavior is clear.
+ .. versionadded:: 3.25
+ The :prop_tgt:`FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>` target property as
+ well as the ``suffix`` of the framework library name are now supported by
+ the ``FRAMEWORK`` features.
+
``NEEDED_FRAMEWORK``
This is similar to the ``FRAMEWORK`` feature, except it forces the linker
to link with the framework even if no symbols are used from it. It uses
diff --git a/Help/variable/LINUX.rst b/Help/variable/LINUX.rst
new file mode 100644
index 000000000..26379b3d0
--- /dev/null
+++ b/Help/variable/LINUX.rst
@@ -0,0 +1,6 @@
+LINUX
+-----
+
+.. versionadded:: 3.25
+
+Set to true when the target system is Linux.
diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in
index f19bc97ab..264332624 100644
--- a/Modules/CMakeCXXCompilerId.cpp.in
+++ b/Modules/CMakeCXXCompilerId.cpp.in
@@ -82,6 +82,7 @@ int main(int argc, char* argv[])
int require = 0;
require += info_compiler[argc];
require += info_platform[argc];
+ require += info_arch[argc];
#ifdef COMPILER_VERSION_MAJOR
require += info_version[argc];
#endif
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index f15974ae0..75d33e89e 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -70,6 +70,7 @@ function(compiler_id_detection outvar lang)
FujitsuClang
Fujitsu
GHS
+ Tasking
)
if ("x${lang}" STREQUAL "xC")
list(APPEND ordered_compilers
diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake
index ac0e2624a..9a3c94067 100644
--- a/Modules/CMakeDependentOption.cmake
+++ b/Modules/CMakeDependentOption.cmake
@@ -84,7 +84,7 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force)
else()
set(${option} "${${option}_ISSET}")
endif()
- if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_; ]")
+ if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_.; ]")
cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING)
message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}")
endif()
diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index d03cbef01..5ec2972b0 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -129,14 +129,13 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
if("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xIAR")
# primary necessary to detect architecture, so the right archiver and linker can be picked
# eg. "IAR Assembler V8.10.1.12857/W32 for ARM" or "IAR Assembler V4.11.1.4666 for Renesas RX"
- # Cut out identification first, newline handling is a pain
+ # Earlier versions did not provide `--version`, so grep the full output to extract Assembler ID string
string(REGEX MATCH "IAR Assembler[^\r\n]*" _compileid "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_OUTPUT}")
if("${_compileid}" MATCHES "V([0-9]+\\.[0-9]+\\.[0-9]+)")
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_VERSION ${CMAKE_MATCH_1})
endif()
- string(REGEX MATCHALL "([A-Za-z0-9-]+)" _all_compileid_matches "${_compileid}")
- if(_all_compileid_matches)
- list(GET _all_compileid_matches "-1" CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID)
+ if("${_compileid}" MATCHES "for.*(MSP430|8051|ARM|AVR|RH850|RISC-?V|RL78|RX|STM8|V850)")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID ${CMAKE_MATCH_1})
endif()
elseif("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xClang")
# Test whether an MSVC-like command-line option works.
diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake
index da860a843..fe9846933 100644
--- a/Modules/CMakeDetermineCSharpCompiler.cmake
+++ b/Modules/CMakeDetermineCSharpCompiler.cmake
@@ -3,7 +3,7 @@
if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
message(FATAL_ERROR
- "C# is currently only supported for Microsoft Visual Studio 2010 and later.")
+ "C# is currently only supported for Microsoft Visual Studio 11 2012 and later.")
endif()
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 0ac06ac3b..f43b17bbe 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -275,7 +275,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
if(DEFINED CMAKE_CUDA_ARCHITECTURES)
if(CMAKE_CUDA_ARCHITECTURES STREQUAL "")
message(FATAL_ERROR "CMAKE_CUDA_ARCHITECTURES must be non-empty if set.")
- elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+(-real|-virtual)?(;[0-9]+(-real|-virtual)?|;)*|all|all-major|native)$")
+ elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+a?(-real|-virtual)?(;[0-9]+a?(-real|-virtual)?|;)*|all|all-major|native)$")
message(FATAL_ERROR
"CMAKE_CUDA_ARCHITECTURES:\n"
" ${CMAKE_CUDA_ARCHITECTURES}\n"
@@ -503,7 +503,8 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
log
- "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
+ "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}"
+ LANGUAGE CUDA)
# Detect CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT from the compiler by looking at which
# cudart library exists in the implicit link libraries passed to the host linker.
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index a08e597f8..09de7b11f 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -63,6 +63,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CXX17_COMPILE_FEATURES)
set(CMAKE_CXX20_COMPILE_FEATURES)
set(CMAKE_CXX23_COMPILE_FEATURES)
+ set(CMAKE_CXX26_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -73,6 +74,9 @@ function(cmake_determine_compile_features lang)
return()
endif()
+ if (CMAKE_CXX23_COMPILE_FEATURES AND CMAKE_CXX26_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES})
+ endif()
if (CMAKE_CXX20_COMPILE_FEATURES AND CMAKE_CXX23_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES})
endif()
@@ -97,6 +101,7 @@ function(cmake_determine_compile_features lang)
${CMAKE_CXX17_COMPILE_FEATURES}
${CMAKE_CXX20_COMPILE_FEATURES}
${CMAKE_CXX23_COMPILE_FEATURES}
+ ${CMAKE_CXX26_COMPILE_FEATURES}
)
endif()
@@ -107,6 +112,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX26_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
@@ -119,6 +125,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CUDA17_COMPILE_FEATURES)
set(CMAKE_CUDA20_COMPILE_FEATURES)
set(CMAKE_CUDA23_COMPILE_FEATURES)
+ set(CMAKE_CUDA26_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -129,6 +136,9 @@ function(cmake_determine_compile_features lang)
return()
endif()
+ if (CMAKE_CUDA23_COMPILE_FEATURES AND CMAKE_CUDA26_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_CUDA26_COMPILE_FEATURES ${CMAKE_CUDA23_COMPILE_FEATURES})
+ endif()
if (CMAKE_CUDA20_COMPILE_FEATURES AND CMAKE_CUDA23_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES})
endif()
@@ -153,6 +163,7 @@ function(cmake_determine_compile_features lang)
${CMAKE_CUDA17_COMPILE_FEATURES}
${CMAKE_CUDA20_COMPILE_FEATURES}
${CMAKE_CUDA23_COMPILE_FEATURES}
+ ${CMAKE_CUDA26_COMPILE_FEATURES}
)
endif()
@@ -163,6 +174,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA23_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_CUDA26_COMPILE_FEATURES ${CMAKE_CUDA26_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
@@ -175,6 +187,8 @@ function(cmake_determine_compile_features lang)
set(CMAKE_HIP17_COMPILE_FEATURES)
set(CMAKE_HIP20_COMPILE_FEATURES)
set(CMAKE_HIP23_COMPILE_FEATURES)
+ set(CMAKE_HIP26_COMPILE_FEATURES)
+
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -185,6 +199,9 @@ function(cmake_determine_compile_features lang)
return()
endif()
+ if (CMAKE_HIP23_COMPILE_FEATURES AND CMAKE_HIP26_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP26_COMPILE_FEATURES ${CMAKE_HIP23_COMPILE_FEATURES})
+ endif()
if (CMAKE_HIP20_COMPILE_FEATURES AND CMAKE_HIP23_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES})
endif()
@@ -209,6 +226,7 @@ function(cmake_determine_compile_features lang)
${CMAKE_HIP17_COMPILE_FEATURES}
${CMAKE_HIP20_COMPILE_FEATURES}
${CMAKE_HIP23_COMPILE_FEATURES}
+ ${CMAKE_HIP26_COMPILE_FEATURES}
)
endif()
@@ -219,6 +237,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_HIP17_COMPILE_FEATURES ${CMAKE_HIP17_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_HIP20_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP23_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_HIP26_COMPILE_FEATURES ${CMAKE_HIP26_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake
index 82a6d21a4..053effa2c 100644
--- a/Modules/CMakeDetermineCompilerABI.cmake
+++ b/Modules/CMakeDetermineCompilerABI.cmake
@@ -55,7 +55,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
set(ENV{LANG} C)
try_compile(CMAKE_${lang}_ABI_COMPILED
- ${CMAKE_BINARY_DIR} ${src}
+ SOURCES ${src}
CMAKE_FLAGS ${CMAKE_FLAGS}
# Ignore unused flags when we are just determining the ABI.
"--no-warn-unused-cli"
@@ -149,7 +149,8 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
if(CMAKE_${lang}_VERBOSE_FLAG)
CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log
"${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}"
- COMPUTE_IMPLICIT_OBJECTS implicit_objs)
+ COMPUTE_IMPLICIT_OBJECTS implicit_objs
+ LANGUAGE ${lang})
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Parsed ${lang} implicit link information from above output:\n${log}\n\n")
endif()
@@ -161,8 +162,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
message(CHECK_START "Determine Intel Fortran Compiler Implicit Link Path")
# Build a sample project which reports symbols.
try_compile(IFORT_LIB_PATH_COMPILED
- ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath
- ${CMAKE_ROOT}/Modules/IntelVSImplicitPath
+ PROJECT IntelFortranImplicit
+ SOURCE_DIR ${CMAKE_ROOT}/Modules/IntelVSImplicitPath
+ BINARY_DIR ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath
IntelFortranImplicit
CMAKE_FLAGS
"-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 2b19736d4..73c775aeb 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -720,7 +720,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line"
)
# Compilation failed.
- set(MSG
+ string(APPEND _CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG
"Compiling the ${lang} compiler identification source file \"${src}\" failed.
${COMPILER_DESCRIPTION}
The output was:
@@ -736,7 +736,11 @@ ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
# Some languages may know the correct/desired set of flags and want to fail right away if they don't work.
# This is currently only used by CUDA.
if(__compiler_id_require_success)
- message(FATAL_ERROR "${MSG}")
+ message(FATAL_ERROR "${_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG}")
+ else()
+ # Build up the outputs for compiler detection attempts so that users
+ # can see all set of flags tried, instead of just last
+ set(_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG "${_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG}" PARENT_SCOPE)
endif()
# No output files should be inspected.
@@ -1123,7 +1127,7 @@ function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags)
OUTPUT_VARIABLE out
ERROR_VARIABLE err
RESULT_VARIABLE res
- ENCODING AUTO # cl prints in current code page
+ ENCODING AUTO # cl prints in console output code page
)
if(res EQUAL 0 AND "${out}" MATCHES "(^|\n)([^:\n]*:[^:\n]*:[ \t]*)")
set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_MATCH_2}" PARENT_SCOPE)
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index 650c87a70..087c0f6c0 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -44,17 +44,14 @@ else()
# finally list compilers to try
if(NOT CMAKE_Fortran_COMPILER_INIT)
# Known compilers:
- # f77/f90/f95: generic compiler names
# ftn: Cray fortran compiler wrapper
- # g77: GNU Fortran 77 compiler
# gfortran: putative GNU Fortran 95+ compiler (in progress)
- # fort77: native F77 compiler under HP-UX (and some older Crays)
- # frt: Fujitsu F77 compiler
+ # frt: Fujitsu Fortran compiler
# pathf90/pathf95/pathf2003: PathScale Fortran compiler
- # pgf77/pgf90/pgf95/pgfortran: Portland Group F77/F90/F95 compilers
+ # pgfortran: Portland Group Fortran compilers
# nvfortran: NVHPC Fotran compiler
# flang: Flang Fortran compiler
- # xlf/xlf90/xlf95: IBM (AIX) F77/F90/F95 compilers
+ # xlf: IBM (AIX) Fortran compiler
# lf95: Lahey-Fujitsu F95 compiler
# fl32: Microsoft Fortran 77 "PowerStation" compiler
# af77: Apogee F77 compiler for Intergraph hardware running CLIX
@@ -62,31 +59,20 @@ else()
# fort: Compaq (now HP) Fortran 90/95 compiler for Tru64 and Linux/Alpha
# ifx: Intel Fortran LLVM-based compiler
# ifort: Intel Classic Fortran compiler
- # ifc: Intel Fortran 95 compiler for Linux/x86
- # efc: Intel Fortran 95 compiler for IA64
# nagfor: NAG Fortran compiler
#
- # The order is 95 or newer compilers first, then 90,
- # then 77 or older compilers, gnu is always last in the group,
+ # GNU is last to be searched,
# so if you paid for a compiler it is picked by default.
- if(CMAKE_HOST_WIN32)
- set(CMAKE_Fortran_COMPILER_LIST
- ifort ifx pgf95 pgfortran nvfortran lf95 fort
- flang gfortran gfortran-4 g95 f90 pgf90
- pgf77 g77 f77 nag
- )
- else()
- set(CMAKE_Fortran_COMPILER_LIST
- ftn
- ifort ifc ifx efc pgf95 pgfortran nvfortran lf95 xlf95 fort
- flang lfortran gfortran gfortran-4 g95 f90 pgf90
- frt pgf77 xlf g77 f77 nag
- )
- endif()
+ set(CMAKE_Fortran_COMPILER_LIST
+ ftn
+ ifx ifort nvfortran pgfortran lf95 xlf fort
+ flang lfortran frt nagfor
+ gfortran
+ )
# Vendor-specific compiler names.
set(_Fortran_COMPILER_NAMES_LCC lfortran gfortran)
- set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77)
+ set(_Fortran_COMPILER_NAMES_GNU gfortran)
set(_Fortran_COMPILER_NAMES_Intel ifort ifc efc ifx)
set(_Fortran_COMPILER_NAMES_Absoft af95 af90 af77)
set(_Fortran_COMPILER_NAMES_PGI pgf95 pgfortran pgf90 pgf77)
diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake
index 7b7d7a3b4..6294d047c 100644
--- a/Modules/CMakeDetermineHIPCompiler.cmake
+++ b/Modules/CMakeDetermineHIPCompiler.cmake
@@ -86,6 +86,7 @@ if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT AND CMAKE_HIP_COMPILER_ID STREQUAL "Clang")
if(_CMAKE_HIP_COMPILER_RESULT EQUAL 0 AND _CMAKE_HIP_COMPILER_STDERR MATCHES "Found HIP installation: *([^,]*)[,\n]")
set(CMAKE_HIP_COMPILER_ROCM_ROOT "${CMAKE_MATCH_1}")
+ file(TO_CMAKE_PATH "${CMAKE_HIP_COMPILER_ROCM_ROOT}" CMAKE_HIP_COMPILER_ROCM_ROOT)
endif()
endif()
if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT)
diff --git a/Modules/CMakeDetermineVSServicePack.cmake b/Modules/CMakeDetermineVSServicePack.cmake
index 53868d21a..0d360b531 100644
--- a/Modules/CMakeDetermineVSServicePack.cmake
+++ b/Modules/CMakeDetermineVSServicePack.cmake
@@ -105,8 +105,7 @@ function(_DetermineVSServicePack_CheckVersionWithTryCompile _SUCCESS_VAR _VERSI
try_compile(
_CompileResult
- "${CMAKE_BINARY_DIR}"
- "${CMAKE_BINARY_DIR}/return0.cc"
+ SOURCES "${CMAKE_BINARY_DIR}/return0.cc"
OUTPUT_VARIABLE _output
COPY_FILE "${CMAKE_BINARY_DIR}/return0.cc")
@@ -128,8 +127,7 @@ function(_DetermineVSServicePack_CheckVersionWithTryRun _SUCCESS_VAR _VERSION_V
try_run(
_RunResult
_CompileResult
- "${CMAKE_BINARY_DIR}"
- "${CMAKE_BINARY_DIR}/return0.cc"
+ SOURCES "${CMAKE_BINARY_DIR}/return0.cc"
RUN_OUTPUT_VARIABLE _runoutput
)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index a6bd0d192..2ac887992 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -170,7 +170,7 @@ else()
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang)
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC")
list(PREPEND _CMAKE_LINKER_NAMES "lld-link")
- else()
+ elseif(NOT APPLE)
list(PREPEND _CMAKE_LINKER_NAMES "ld.lld")
endif()
if(APPLE)
diff --git a/Modules/CMakeFindFrameworks.cmake b/Modules/CMakeFindFrameworks.cmake
index 8906f48f3..1aa392947 100644
--- a/Modules/CMakeFindFrameworks.cmake
+++ b/Modules/CMakeFindFrameworks.cmake
@@ -17,12 +17,19 @@ if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED)
macro(CMAKE_FIND_FRAMEWORKS fwk)
set(${fwk}_FRAMEWORKS)
if(APPLE)
+ # 'Frameworks' directory from Brew (Apple Silicon and Intel)
+ if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+ set(_brew_framework_path /opt/homebrew/Frameworks)
+ else()
+ set(_brew_framework_path /usr/local/Frameworks)
+ endif()
+
file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _cmff_CMAKE_FRAMEWORK_PATH)
set(_cmff_search_paths
${CMAKE_FRAMEWORK_PATH}
${_cmff_CMAKE_FRAMEWORK_PATH}
~/Library/Frameworks
- /usr/local/Frameworks
+ ${_brew_framework_path}
/Library/Frameworks
/System/Library/Frameworks
/Network/Library/Frameworks
diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake
index 4c5767767..33f8697e5 100644
--- a/Modules/CMakeHIPInformation.cmake
+++ b/Modules/CMakeHIPInformation.cmake
@@ -143,7 +143,7 @@ set(CMAKE_HIP_INFORMATION_LOADED 1)
# Load the file and find the relevant HIP runtime.
if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET)
set(hip-lang_DIR "${CMAKE_HIP_COMPILER_ROCM_ROOT}/lib/cmake/hip-lang")
- find_package(hip-lang CONFIG QUIET NO_DEFAULT_PATH)
+ find_package(hip-lang CONFIG QUIET NO_DEFAULT_PATH REQUIRED)
endif()
if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET)
list(APPEND CMAKE_HIP_RUNTIME_LIBRARIES_STATIC ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET})
diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake
index 6bdefde83..1773dc4f2 100644
--- a/Modules/CMakeParseImplicitLinkInfo.cmake
+++ b/Modules/CMakeParseImplicitLinkInfo.cmake
@@ -22,7 +22,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
set(log "")
set(keywordArgs)
- set(oneValueArgs COMPUTE_IMPLICIT_OBJECTS)
+ set(oneValueArgs COMPUTE_IMPLICIT_OBJECTS LANGUAGE)
set(multiValueArgs )
cmake_parse_arguments(EXTRA_PARSE "${keywordArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -76,6 +76,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
endif()
endif()
set(is_msvc 0)
+ if(EXTRA_PARSE_LANGUAGE AND
+ ("x${CMAKE_${EXTRA_PARSE_LANGUAGE}_ID}" STREQUAL "xMSVC" OR
+ "x${CMAKE_${EXTRA_PARSE_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC"))
+ set(is_msvc 1)
+ endif()
set(search_static 0)
if("${cmd}" MATCHES "${linker_regex}")
string(APPEND log " link line: [${line}]\n")
diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in
index 06f5ecd23..32b71663c 100644
--- a/Modules/CMakePlatformId.h.in
+++ b/Modules/CMakePlatformId.h.in
@@ -242,6 +242,30 @@
# elif defined(__ADSPBLACKFIN__)
# define ARCHITECTURE_ID "Blackfin"
+#elif defined(__TASKING__)
+
+# if defined(__CTC__) || defined(__CPTC__)
+# define ARCHITECTURE_ID "TriCore"
+
+# elif defined(__CMCS__)
+# define ARCHITECTURE_ID "MCS"
+
+# elif defined(__CARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__CARC__)
+# define ARCHITECTURE_ID "ARC"
+
+# elif defined(__C51__)
+# define ARCHITECTURE_ID "8051"
+
+# elif defined(__CPCP__)
+# define ARCHITECTURE_ID "PCP"
+
+# else
+# define ARCHITECTURE_ID ""
+# endif
+
#else
# define ARCHITECTURE_ID
#endif
diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake
index ecad1d51e..16726d2d2 100644
--- a/Modules/CMakeSwiftInformation.cmake
+++ b/Modules/CMakeSwiftInformation.cmake
@@ -65,7 +65,7 @@ set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -libc MD)
set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -libc MTd)
set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -libc MDd)
-set(CMAKE_Swift_FLAGS_DEBUG_INIT "-g")
+set(CMAKE_Swift_FLAGS_DEBUG_INIT "-Onone -g")
set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake
index e0459321c..b5dc8d3ed 100644
--- a/Modules/CMakeSystemSpecificInformation.cmake
+++ b/Modules/CMakeSystemSpecificInformation.cmake
@@ -16,6 +16,8 @@ set(UNIX )
set(CYGWIN )
set(MSYS )
set(WIN32 )
+set(BSD )
+set(LINUX )
function(_cmake_record_install_prefix )
set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake
index ae5aa27af..a7067675f 100644
--- a/Modules/CMakeTestCCompiler.cmake
+++ b/Modules/CMakeTestCCompiler.cmake
@@ -38,7 +38,7 @@ endif()
if(NOT CMAKE_C_COMPILER_WORKS)
PrintTestCompilerStatus("C")
__TestCompiler_setTryCompileTargetType()
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c
+ string(CONCAT __TestCompiler_testCCompilerSource
"#ifdef __cplusplus\n"
"# error \"The CMAKE_C_COMPILER is set to a C++ compiler\"\n"
"#endif\n"
@@ -53,9 +53,10 @@ if(NOT CMAKE_C_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_C_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c
+ try_compile(CMAKE_C_COMPILER_WORKS
+ SOURCE_FROM_VAR testCCompiler.c __TestCompiler_testCCompilerSource
OUTPUT_VARIABLE __CMAKE_C_COMPILER_OUTPUT)
+ unset(__TestCompiler_testCCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_C_COMPILER_WORKS ${CMAKE_C_COMPILER_WORKS})
unset(CMAKE_C_COMPILER_WORKS CACHE)
diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake
index adea250fa..1c9e2493e 100644
--- a/Modules/CMakeTestCSharpCompiler.cmake
+++ b/Modules/CMakeTestCSharpCompiler.cmake
@@ -12,8 +12,6 @@ include(CMakeTestCompilerCommon)
unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
-set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs")
-
# This file is used by EnableLanguage in cmGlobalGenerator to
# determine that the selected C# compiler can actually compile
# and link the most basic of programs. If not, a fatal error
@@ -23,19 +21,21 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS)
# Don't call PrintTestCompilerStatus() because the "C#" we want to pass
# as the LANG doesn't match with the variable name "CMAKE_CSharp_COMPILER"
message(CHECK_START "Check for working C# compiler: ${CMAKE_CSharp_COMPILER}")
- file(WRITE "${test_compile_file}"
- "namespace Test {"
- " public class CSharp {"
- " static void Main(string[] args) {}"
- " }"
- "}"
+ string(CONCAT __TestCompiler_testCSharpCompilerSource
+ "namespace Test {\n"
+ " public class CSharp {\n"
+ " static void Main(string[] args) {}\n"
+ " }\n"
+ "}\n"
)
# Clear result from normal variable.
unset(CMAKE_CSharp_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_BINARY_DIR} "${test_compile_file}"
+ try_compile(CMAKE_CSharp_COMPILER_WORKS
+ SOURCE_FROM_VAR testCSharpCompiler.cs __TestCompiler_testCSharpCompilerSource
OUTPUT_VARIABLE __CMAKE_CSharp_COMPILER_OUTPUT
)
+ unset(__TestCompiler_testCSharpCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS})
unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake
index 853d65581..f2fa6ea90 100644
--- a/Modules/CMakeTestCUDACompiler.cmake
+++ b/Modules/CMakeTestCUDACompiler.cmake
@@ -76,7 +76,7 @@ endif()
# any makefiles or projects.
if(NOT CMAKE_CUDA_COMPILER_WORKS)
PrintTestCompilerStatus("CUDA")
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu
+ string(CONCAT __TestCompiler_testCudaCompilerSource
"#ifndef __CUDACC__\n"
"# error \"The CMAKE_CUDA_COMPILER is set to an invalid CUDA compiler\"\n"
"#endif\n"
@@ -86,9 +86,10 @@ if(NOT CMAKE_CUDA_COMPILER_WORKS)
unset(CMAKE_CUDA_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu
+ try_compile(CMAKE_CUDA_COMPILER_WORKS
+ SOURCE_FROM_VAR main.cu __TestCompiler_testCudaCompilerSource
OUTPUT_VARIABLE __CMAKE_CUDA_COMPILER_OUTPUT)
+ unset(__TestCompiler_testCudaCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_CUDA_COMPILER_WORKS})
diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake
index bbe35334b..fa4016a2b 100644
--- a/Modules/CMakeTestCXXCompiler.cmake
+++ b/Modules/CMakeTestCXXCompiler.cmake
@@ -38,7 +38,7 @@ endif()
if(NOT CMAKE_CXX_COMPILER_WORKS)
PrintTestCompilerStatus("CXX")
__TestCompiler_setTryCompileTargetType()
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx
+ string(CONCAT __TestCompiler_testCXXCompilerSource
"#ifndef __cplusplus\n"
"# error \"The CMAKE_CXX_COMPILER is set to a C compiler\"\n"
"#endif\n"
@@ -46,9 +46,10 @@ if(NOT CMAKE_CXX_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_CXX_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_CXX_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx
+ try_compile(CMAKE_CXX_COMPILER_WORKS
+ SOURCE_FROM_VAR testCXXCompiler.cxx __TestCompiler_testCXXCompilerSource
OUTPUT_VARIABLE __CMAKE_CXX_COMPILER_OUTPUT)
+ unset(__TestCompiler_testCXXCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_CXX_COMPILER_WORKS ${CMAKE_CXX_COMPILER_WORKS})
unset(CMAKE_CXX_COMPILER_WORKS CACHE)
@@ -56,7 +57,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS)
if(NOT CMAKE_CXX_COMPILER_WORKS)
PrintTestCompilerResult(CHECK_FAIL "broken")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining if the CXX compiler works failed with "
+ "Determining if the C++ compiler works failed with "
"the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n")
string(REPLACE "\n" "\n " _output "${__CMAKE_CXX_COMPILER_OUTPUT}")
message(FATAL_ERROR "The C++ compiler\n \"${CMAKE_CXX_COMPILER}\"\n"
@@ -66,7 +67,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS)
endif()
PrintTestCompilerResult(CHECK_PASS "works")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Determining if the CXX compiler works passed with "
+ "Determining if the C++ compiler works passed with "
"the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n")
endif()
diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake
index 579f83ff8..e6d1f6d5e 100644
--- a/Modules/CMakeTestFortranCompiler.cmake
+++ b/Modules/CMakeTestFortranCompiler.cmake
@@ -38,7 +38,7 @@ endif()
# any makefiles or projects.
if(NOT CMAKE_Fortran_COMPILER_WORKS)
PrintTestCompilerStatus("Fortran")
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f "
+ set(__TestCompiler_testFortranCompilerSource "
PROGRAM TESTFortran
PRINT *, 'Hello'
END
@@ -46,9 +46,10 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_Fortran_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f
+ try_compile(CMAKE_Fortran_COMPILER_WORKS
+ SOURCE_FROM_VAR testFortranCompiler.f __TestCompiler_testFortranCompilerSource
OUTPUT_VARIABLE OUTPUT)
+ unset(__TestCompiler_testFortranCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_Fortran_COMPILER_WORKS})
unset(CMAKE_Fortran_COMPILER_WORKS CACHE)
@@ -72,14 +73,15 @@ endif()
# Test for Fortran 90 support by using an f90-specific construct.
if(NOT DEFINED CMAKE_Fortran_COMPILER_SUPPORTS_F90)
message(CHECK_START "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90")
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 "
+ set(__TestCompiler_testFortranCompilerSource "
PROGRAM TESTFortran90
integer stop ; stop = 1 ; do while ( stop .eq. 0 ) ; end do
END PROGRAM TESTFortran90
")
- try_compile(CMAKE_Fortran_COMPILER_SUPPORTS_F90 ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90
+ try_compile(CMAKE_Fortran_COMPILER_SUPPORTS_F90
+ SOURCE_FROM_VAR testFortranCompilerF90.f90 __TestCompiler_testFortranCompilerF90Source
OUTPUT_VARIABLE OUTPUT)
+ unset(__TestCompiler_testFortranCompilerF90Source)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
message(CHECK_PASS "yes")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake
index ecbfa7fc2..1da0ae4ef 100644
--- a/Modules/CMakeTestHIPCompiler.cmake
+++ b/Modules/CMakeTestHIPCompiler.cmake
@@ -41,7 +41,7 @@ endif()
if(NOT CMAKE_HIP_COMPILER_WORKS)
PrintTestCompilerStatus("HIP")
__TestCompiler_setTryCompileTargetType()
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip
+ string(CONCAT __TestCompiler_testHIPCompilerSource
"#ifndef __HIP__\n"
"# error \"The CMAKE_HIP_COMPILER is set to a C/CXX compiler\"\n"
"#endif\n"
@@ -49,9 +49,10 @@ if(NOT CMAKE_HIP_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_HIP_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_HIP_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip
+ try_compile(CMAKE_HIP_COMPILER_WORKS
+ SOURCE_FROM_VAR testHIPCompiler.hip __TestCompiler_testHIPCompilerSource
OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT)
+ unset(__TestCompiler_testHIPCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_HIP_COMPILER_WORKS ${CMAKE_HIP_COMPILER_WORKS})
unset(CMAKE_HIP_COMPILER_WORKS CACHE)
diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake
index 20d1f8be9..bbc90a76b 100644
--- a/Modules/CMakeTestOBJCCompiler.cmake
+++ b/Modules/CMakeTestOBJCCompiler.cmake
@@ -38,7 +38,7 @@ endif()
if(NOT CMAKE_OBJC_COMPILER_WORKS)
PrintTestCompilerStatus("OBJC")
__TestCompiler_setTryCompileTargetType()
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+ string(CONCAT __TestCompiler_testObjCCompilerSource
"#ifdef __cplusplus\n"
"# error \"The CMAKE_OBJC_COMPILER is set to a C++ compiler\"\n"
"#endif\n"
@@ -50,9 +50,10 @@ if(NOT CMAKE_OBJC_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_OBJC_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+ try_compile(CMAKE_OBJC_COMPILER_WORKS
+ SOURCE_FROM_VAR testObjCCompiler.m __TestCompiler_testObjCCompilerSource
OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT)
+ unset(__TestCompiler_testObjCCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS})
unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake
index 4f7185f70..aceb939c1 100644
--- a/Modules/CMakeTestOBJCXXCompiler.cmake
+++ b/Modules/CMakeTestOBJCXXCompiler.cmake
@@ -38,7 +38,7 @@ endif()
if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
PrintTestCompilerStatus("OBJCXX")
__TestCompiler_setTryCompileTargetType()
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+ string(CONCAT __TestCompiler_testObjCXXCompilerSource
"#ifndef __cplusplus\n"
"# error \"The CMAKE_OBJCXX_COMPILER is set to a C compiler\"\n"
"#endif\n"
@@ -49,9 +49,10 @@ if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
# Clear result from normal variable.
unset(CMAKE_OBJCXX_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+ try_compile(CMAKE_OBJCXX_COMPILER_WORKS
+ SOURCE_FROM_VAR testObjCXXCompiler.mm __TestCompiler_testObjCXXCompilerSource
OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT)
+ unset(__TestCompiler_testObjCXXCompilerSource)
# Move result from cache to normal variable.
set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS})
unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake
index 2f2546f86..88a864cc7 100644
--- a/Modules/CMakeTestSwiftCompiler.cmake
+++ b/Modules/CMakeTestSwiftCompiler.cmake
@@ -21,13 +21,12 @@ unset(CMAKE_Swift_COMPILER_WORKS CACHE)
# any makefiles or projects.
if(NOT CMAKE_Swift_COMPILER_WORKS)
PrintTestCompilerStatus("Swift")
- file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift
- "print(\"CMake\")\n")
# Clear result from normal variable.
unset(CMAKE_Swift_COMPILER_WORKS)
# Puts test result in cache variable.
- try_compile(CMAKE_Swift_COMPILER_WORKS ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift
+ set(__CMAKE_Swift_TEST_SOURCE "print(\"CMake\")\n")
+ try_compile(CMAKE_Swift_COMPILER_WORKS
+ SOURCE_FROM_VAR main.swift __CMAKE_Swift_TEST_SOURCE
OUTPUT_VARIABLE __CMAKE_Swift_COMPILER_OUTPUT)
# Move result from cache to normal variable.
set(CMAKE_Swift_COMPILER_WORKS ${CMAKE_Swift_COMPILER_WORKS})
@@ -64,4 +63,5 @@ else()
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake)
endif()
+unset(__CMAKE_Swift_TEST_SOURCE)
unset(__CMAKE_Swift_COMPILER_OUTPUT)
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 49349341b..7c3ad6b89 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -53,9 +53,9 @@ Here's how it works:
* :manual:`cpack <cpack(1)>` runs
* it includes ``CPackConfig.cmake``
-* it iterates over the generators given by the ``-G`` command line option,
- or if no such option was specified, over the list of generators given by
- the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake``
+* it iterates over the generators given by the :option:`-G <cpack -G>` command
+ line option, or if no such option was specified, over the list of generators
+ given by the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake``
input file.
* foreach generator, it then
@@ -217,7 +217,8 @@ installers. The most commonly-used variables are:
to the user by the produced installer (often with an explicit "Accept"
button, for graphical installers) prior to installation. This license
file is NOT added to the installed files but is used by some CPack generators
- like NSIS. If you want to install a license file (may be the same as this
+ like NSIS. If you want to use UTF-8 characters, the file needs to be encoded
+ in UTF-8 BOM. If you want to install a license file (may be the same as this
one) along with your project, you must add an appropriate CMake
:command:`install` command in your ``CMakeLists.txt``.
@@ -246,9 +247,9 @@ installers. The most commonly-used variables are:
List of CPack generators to use. If not specified, CPack will create a
set of options following the naming pattern
:variable:`CPACK_BINARY_<GENNAME>` (e.g. ``CPACK_BINARY_NSIS``) allowing
- the user to enable/disable individual generators. If the ``-G`` option is
- given on the :manual:`cpack <cpack(1)>` command line, it will override this
- variable and any ``CPACK_BINARY_<GENNAME>`` options.
+ the user to enable/disable individual generators. If the :option:`-G <cpack -G>`
+ option is given on the :manual:`cpack <cpack(1)>` command line, it will override
+ this variable and any ``CPACK_BINARY_<GENNAME>`` options.
.. variable:: CPACK_OUTPUT_CONFIG_FILE
@@ -469,7 +470,35 @@ The following variables are for advanced uses of CPack:
generates (when :variable:`CPACK_GENERATOR` is not set) a set of CMake
options (see CMake :command:`option` command) which may then be used to
select the CPack generator(s) to be used when building the ``package``
- target or when running :manual:`cpack <cpack(1)>` without the ``-G`` option.
+ target or when running :manual:`cpack <cpack(1)>` without the
+ :option:`-G <cpack -G>` option.
+
+.. variable:: CPACK_READELF_EXECUTABLE
+
+ .. versionadded:: 3.25
+
+ Specify the ``readelf`` executable path used by CPack.
+ The default value will be ``CMAKE_READELF`` when set. Otherwise,
+ the default value will be empty and CPack will use :command:`find_program`
+ to determine the ``readelf`` path when needed.
+
+.. variable:: CPACK_OBJCOPY_EXECUTABLE
+
+ .. versionadded:: 3.25
+
+ Specify the ``objcopy`` executable path used by CPack.
+ The default value will be ``CMAKE_OBJCOPY`` when set. Otherwise,
+ the default value will be empty and CPack will use :command:`find_program`
+ to determine the ``objcopy`` path when needed.
+
+.. variable:: CPACK_OBJDUMP_EXECUTABLE
+
+ .. versionadded:: 3.25
+
+ Specify the ``objdump`` executable path used by CPack.
+ The default value will be ``CMAKE_OBJDUMP`` when set. Otherwise,
+ the default value will be empty and CPack will use :command:`find_program`
+ to determine the ``objdump`` path when needed.
#]=======================================================================]
@@ -590,6 +619,16 @@ _cpack_set_default(CPACK_RESOURCE_FILE_WELCOME
_cpack_set_default(CPACK_MODULE_PATH "${CMAKE_MODULE_PATH}")
+if(CMAKE_READELF)
+ _cpack_set_default(CPACK_READELF_EXECUTABLE "${CMAKE_READELF}")
+endif()
+if(CMAKE_OBJCOPY)
+ _cpack_set_default(CPACK_OBJCOPY_EXECUTABLE "${CMAKE_OBJCOPY}")
+endif()
+if(CMAKE_OBJDUMP)
+ _cpack_set_default(CPACK_OBJDUMP_EXECUTABLE "${CMAKE_OBJDUMP}")
+endif()
+
# Set default directory creation permissions mode
if(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)
_cpack_set_default(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 8ca9f2892..529f4e7d9 100644
--- a/Modules/CPackComponent.cmake
+++ b/Modules/CPackComponent.cmake
@@ -301,7 +301,7 @@ be built and installed on system using macOS 10.5 or later.
The site argument is a URL where the archives for downloadable
components will reside, e.g.,
-https://cmake.org/files/2.6.1/installer/ All of the archives
+https://cmake.org/files/v3.25/ All of the archives
produced by CPack should be uploaded to that location.
UPLOAD_DIRECTORY is the local directory where CPack will create the
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index a4bfe1d25..d4e02f122 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -439,37 +439,57 @@ set(_CPACK_IFW_PREFIXES
"QtIFW-")
set(_CPACK_IFW_VERSIONS
+ "4.5.0"
+ "4.5"
+ "4.4.2"
+ "4.4.1"
+ "4.4.0"
"4.4"
+ "4.3.0"
"4.3"
+ "4.2.0"
"4.2"
+ "4.1.1"
+ "4.1.0"
"4.1"
+ "4.0.1"
+ "4.0.0"
"4.0"
- "3.2"
+ "3.2.3"
+ "3.2.2"
+ "3.2.1"
"3.2.0"
- "3.1"
+ "3.2"
+ "3.1.1"
"3.1.0"
- "3.0"
+ "3.1"
+ "3.0.6"
+ "3.0.4"
+ "3.0.3"
+ "3.0.2"
+ "3.0.1"
"3.0.0"
- "2.3"
+ "3.0"
"2.3.0"
- "2.2"
+ "2.3"
"2.2.0"
- "2.1"
+ "2.2"
"2.1.0"
- "2.0"
+ "2.1"
"2.0.5"
"2.0.3"
"2.0.2"
"2.0.1"
"2.0.0"
- "1.6"
+ "2.0"
"1.6.0"
- "1.5"
+ "1.6"
"1.5.0"
- "1.4"
+ "1.5"
"1.4.0"
- "1.3"
- "1.3.0")
+ "1.4"
+ "1.3.0"
+ "1.3")
set(_CPACK_IFW_SUFFIXES "bin")
foreach(_CPACK_IFW_PREFIX ${_CPACK_IFW_PREFIXES})
diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 8f8ebb4b7..16283d6ae 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -33,7 +33,7 @@ file at the top of the project with content such as::
(the CDash server can provide the file to a project administrator who
configures ``MyProject``). Settings in the config file are shared by
both this ``CTest`` module and the :manual:`ctest(1)` command-line
-:ref:`Dashboard Client` mode (``ctest -S``).
+:ref:`Dashboard Client` mode (:option:`ctest -S`).
While building a project for submission to CDash, CTest scans the
build output for errors and warnings and reports them with surrounding
diff --git a/Modules/CTestTargets.cmake b/Modules/CTestTargets.cmake
index 838fbbfeb..b91b48eec 100644
--- a/Modules/CTestTargets.cmake
+++ b/Modules/CTestTargets.cmake
@@ -86,7 +86,7 @@ if(NOT _CTEST_TARGETS_ADDED)
# or "RUN_TESTS" target:
if(CTEST_TEST_TARGET_ALIAS)
add_custom_target(${CTEST_TEST_TARGET_ALIAS}
- ${CMAKE_CTEST_COMMAND} ${__conf_types}
+ ${CMAKE_CTEST_COMMAND} ${CMAKE_CTEST_ARGUMENTS} ${__conf_types}
USES_TERMINAL
)
endif()
diff --git a/Modules/CTestUseLaunchers.cmake b/Modules/CTestUseLaunchers.cmake
index 23a206b2a..5c544f8cd 100644
--- a/Modules/CTestUseLaunchers.cmake
+++ b/Modules/CTestUseLaunchers.cmake
@@ -11,7 +11,7 @@ CTestUseLaunchers is automatically included when you include(CTest).
However, it is split out into its own module file so projects can use
the CTEST_USE_LAUNCHERS functionality independently.
-To use launchers, set CTEST_USE_LAUNCHERS to ON in a ctest -S
+To use launchers, set CTEST_USE_LAUNCHERS to ON in a :option:`ctest -S`
dashboard script, and then also set it in the cache of the configured
project. Both cmake and ctest need to know the value of it for the
launchers to work properly. CMake needs to know in order to generate
@@ -27,9 +27,12 @@ variable initialization only occurs if CTEST_USE_LAUNCHERS is not
already defined.
.. versionadded:: 3.8
- If CTEST_USE_LAUNCHERS is on in a ctest -S script
+ If CTEST_USE_LAUNCHERS is on in a :option:`ctest -S` script
the ctest_configure command will add -DCTEST_USE_LAUNCHERS:BOOL=TRUE
to the cmake command used to configure the project.
+
+.. TODO Use RST markup
+
#]=======================================================================]
if(NOT DEFINED CTEST_USE_LAUNCHERS AND DEFINED ENV{CTEST_USE_LAUNCHERS_DEFAULT})
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index 7b13c3aa3..1fa089828 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -74,5 +74,5 @@ include_guard(GLOBAL)
include(CheckSymbolExists)
macro(CHECK_CXX_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
- __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
+ __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.cxx "${SYMBOL}" "${FILES}" "${VARIABLE}" )
endmacro()
diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake
index 8f1ca9dd3..7e3a7eeda 100644
--- a/Modules/CheckFortranFunctionExists.cmake
+++ b/Modules/CheckFortranFunctionExists.cmake
@@ -58,8 +58,7 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE)
else()
set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES)
endif()
- file(WRITE
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f
+ set(__CheckFunction_testFortranCompilerSource
"
program TESTFortran
external ${FUNCTION}
@@ -68,12 +67,12 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE)
"
)
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f
+ SOURCE_FROM_VAR testFortranCompiler.f __CheckFunction_testFortranCompilerSource
${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS}
${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}
OUTPUT_VARIABLE OUTPUT
)
+ unset(__CheckFunction_testFortranCompilerSource)
if(${VARIABLE})
set(${VARIABLE} 1 CACHE INTERNAL "Have Fortran function ${FUNCTION}")
message(CHECK_PASS "found")
diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake
index 9efa132b4..60f018410 100644
--- a/Modules/CheckFunctionExists.cmake
+++ b/Modules/CheckFunctionExists.cmake
@@ -81,17 +81,15 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE)
endif()
if(CMAKE_C_COMPILER_LOADED)
- set(_cfe_source ${CMAKE_ROOT}/Modules/CheckFunctionExists.c)
+ set(_cfe_source CheckFunctionExists.c)
elseif(CMAKE_CXX_COMPILER_LOADED)
- set(_cfe_source ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckFunctionExists/CheckFunctionExists.cxx)
- configure_file(${CMAKE_ROOT}/Modules/CheckFunctionExists.c "${_cfe_source}" COPYONLY)
+ set(_cfe_source CheckFunctionExists.cxx)
else()
message(FATAL_ERROR "CHECK_FUNCTION_EXISTS needs either C or CXX language enabled")
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${_cfe_source}
+ SOURCE_FROM_FILE "${_cfe_source}" "${CMAKE_ROOT}/Modules/CheckFunctionExists.c"
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS}
${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
index cca1be905..9108e3414 100644
--- a/Modules/CheckIPOSupported.cmake
+++ b/Modules/CheckIPOSupported.cmake
@@ -76,6 +76,23 @@ endmacro()
# Run IPO/LTO test
macro(_ipo_run_language_check language)
+ set(_C_ext "c")
+ set(_CXX_ext "cpp")
+ set(_Fortran_ext "f")
+ string(COMPARE EQUAL "${language}" "CUDA" is_cuda)
+
+ set(ext ${_${language}_ext})
+ if(NOT "${ext}" STREQUAL "")
+ set(copy_sources foo.${ext} main.${ext})
+ elseif(is_cuda)
+ if(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE)
+ set("${X_RESULT}" YES PARENT_SCOPE)
+ endif()
+ return()
+ else()
+ message(FATAL_ERROR "Language not supported")
+ endif()
+
set(testdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-${language}")
file(REMOVE_RECURSE "${testdir}")
@@ -100,20 +117,6 @@ macro(_ipo_run_language_check language)
@ONLY
)
- string(COMPARE EQUAL "${language}" "C" is_c)
- string(COMPARE EQUAL "${language}" "CXX" is_cxx)
- string(COMPARE EQUAL "${language}" "Fortran" is_fortran)
-
- if(is_c)
- set(copy_sources foo.c main.c)
- elseif(is_cxx)
- set(copy_sources foo.cpp main.cpp)
- elseif(is_fortran)
- set(copy_sources foo.f main.f)
- else()
- message(FATAL_ERROR "Language not supported")
- endif()
-
foreach(x ${copy_sources})
configure_file(
"${try_compile_src}/${x}"
@@ -134,9 +137,9 @@ macro(_ipo_run_language_check language)
try_compile(
_IPO_LANGUAGE_CHECK_RESULT
- "${bindir}"
- "${srcdir}"
- "${TRY_COMPILE_PROJECT_NAME}"
+ PROJECT "${TRY_COMPILE_PROJECT_NAME}"
+ SOURCE_DIR "${srcdir}"
+ BINARY_DIR "${bindir}"
CMAKE_FLAGS
"-DCMAKE_VERBOSE_MAKEFILE=ON"
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON"
@@ -214,6 +217,11 @@ function(check_ipo_supported)
list(APPEND languages "C")
endif()
+ list(FIND enabled_languages "CUDA" result)
+ if(NOT result EQUAL -1)
+ list(APPEND languages "CUDA")
+ endif()
+
list(FIND enabled_languages "Fortran" result)
if(NOT result EQUAL -1)
list(APPEND languages "Fortran")
@@ -222,7 +230,7 @@ function(check_ipo_supported)
string(COMPARE EQUAL "${languages}" "" no_languages)
if(no_languages)
_ipo_not_supported(
- "no C/CXX/Fortran languages found in ENABLED_LANGUAGES global property"
+ "no C/CXX/CUDA/Fortran languages found in ENABLED_LANGUAGES global property"
)
return()
endif()
@@ -230,7 +238,7 @@ function(check_ipo_supported)
set(languages "${X_LANGUAGES}")
set(unsupported_languages "${languages}")
- list(REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran")
+ list(REMOVE_ITEM unsupported_languages "C" "CXX" "CUDA" "Fortran")
string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported)
if(has_unsupported)
_ipo_not_supported(
diff --git a/Modules/CheckIncludeFile.cmake b/Modules/CheckIncludeFile.cmake
index 71ddde7f2..4cba91b3f 100644
--- a/Modules/CheckIncludeFile.cmake
+++ b/Modules/CheckIncludeFile.cmake
@@ -54,8 +54,8 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE)
endif()
set(MACRO_CHECK_INCLUDE_FILE_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CHECK_INCLUDE_FILE_VAR ${INCLUDE})
- configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.c.in
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c)
+ file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.c.in _CIF_SOURCE_CONTENT)
+ string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT)
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_START "Looking for ${INCLUDE}")
endif()
@@ -93,8 +93,7 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE)
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c
+ SOURCE_FROM_VAR CheckIncludeFile.c _CIF_SOURCE_CONTENT
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${_CIF_LINK_OPTIONS}
${_CIF_LINK_LIBRARIES}
diff --git a/Modules/CheckIncludeFileCXX.cmake b/Modules/CheckIncludeFileCXX.cmake
index 953224e76..f6af03692 100644
--- a/Modules/CheckIncludeFileCXX.cmake
+++ b/Modules/CheckIncludeFileCXX.cmake
@@ -53,8 +53,8 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE)
endif()
set(MACRO_CHECK_INCLUDE_FILE_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CHECK_INCLUDE_FILE_VAR ${INCLUDE})
- configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx)
+ file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in _CIF_SOURCE_CONTENT)
+ string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT)
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_START "Looking for C++ include ${INCLUDE}")
endif()
@@ -92,8 +92,7 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE)
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx
+ SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${_CIF_LINK_OPTIONS}
${_CIF_LINK_LIBRARIES}
diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake
index 1800ca888..8e8285987 100644
--- a/Modules/CheckIncludeFiles.cmake
+++ b/Modules/CheckIncludeFiles.cmake
@@ -52,7 +52,7 @@ include_guard(GLOBAL)
macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
if(NOT DEFINED "${VARIABLE}")
- set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
+ set(_src_content "/* */\n")
if("x${ARGN}" STREQUAL "x")
if(CMAKE_C_COMPILER_LOADED)
@@ -71,9 +71,9 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
endif()
if(_lang STREQUAL "C")
- set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.c)
+ set(src ${VARIABLE}.c)
elseif(_lang STREQUAL "CXX")
- set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.cpp)
+ set(src ${VARIABLE}.cpp)
else()
message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n")
endif()
@@ -86,13 +86,11 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
set(CHECK_INCLUDE_FILES_CONTENT "/* */\n")
set(MACRO_CHECK_INCLUDE_FILES_FLAGS ${CMAKE_REQUIRED_FLAGS})
foreach(FILE ${INCLUDE})
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
+ string(APPEND _src_content
"#include <${FILE}>\n")
endforeach()
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
+ string(APPEND _src_content
"\n\nint main(void){return 0;}\n")
- configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
- "${src}" @ONLY)
set(_INCLUDE ${INCLUDE}) # remove empty elements
if("${_INCLUDE}" MATCHES "^([^;]+);.+;([^;]+)$")
@@ -136,8 +134,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
message(CHECK_START "Looking for ${_description}")
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${src}
+ SOURCE_FROM_VAR "${src}" _src_content
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${_CIF_LINK_OPTIONS}
${_CIF_LINK_LIBRARIES}
@@ -164,7 +161,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if files ${INCLUDE} "
"exist failed with the following output:\n"
- "${OUTPUT}\nSource:\n${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
+ "${OUTPUT}\nSource:\n${_src_content}\n")
endif()
endif()
endmacro()
diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake
index 804e0cbba..56424ac27 100644
--- a/Modules/CheckLibraryExists.cmake
+++ b/Modules/CheckLibraryExists.cmake
@@ -61,17 +61,15 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE)
endif()
if(CMAKE_C_COMPILER_LOADED)
- set(_cle_source ${CMAKE_ROOT}/Modules/CheckFunctionExists.c)
+ set(_cle_source CheckFunctionExists.c)
elseif(CMAKE_CXX_COMPILER_LOADED)
- set(_cle_source ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckLibraryExists/CheckFunctionExists.cxx)
- configure_file(${CMAKE_ROOT}/Modules/CheckFunctionExists.c "${_cle_source}" COPYONLY)
+ set(_cle_source CheckFunctionExists.cxx)
else()
message(FATAL_ERROR "CHECK_FUNCTION_EXISTS needs either C or CXX language enabled")
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${_cle_source}
+ SOURCE_FROM_FILE "${_cle_source}" "${CMAKE_ROOT}/Modules/CheckFunctionExists.c"
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_LIBRARY_EXISTS_LINK_OPTIONS}
LINK_LIBRARIES ${CHECK_LIBRARY_EXISTS_LIBRARIES}
diff --git a/Modules/CheckPrototypeDefinition.cmake b/Modules/CheckPrototypeDefinition.cmake
index d29c5e89f..12f4e8684 100644
--- a/Modules/CheckPrototypeDefinition.cmake
+++ b/Modules/CheckPrototypeDefinition.cmake
@@ -94,14 +94,11 @@ function(check_prototype_definition _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIAB
set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
- configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in"
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY)
-
- file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE)
+ file(READ ${__check_proto_def_dir}/CheckPrototypeDefinition.c.in _SOURCE)
+ string(CONFIGURE "${_SOURCE}" _SOURCE @ONLY)
try_compile(${_VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c
+ SOURCE_FROM_VAR CheckPrototypeDefinition.c _SOURCE
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_PROTOTYPE_DEFINITION_LINK_OPTIONS}
${CHECK_PROTOTYPE_DEFINITION_LIBS}
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index a7139af5f..0d44d5655 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -68,11 +68,11 @@ cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
if(CMAKE_C_COMPILER_LOADED)
__CHECK_SYMBOL_EXISTS_FILTER_FLAGS(C)
- __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
+ __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.c "${SYMBOL}" "${FILES}" "${VARIABLE}" )
__CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(C)
elseif(CMAKE_CXX_COMPILER_LOADED)
__CHECK_SYMBOL_EXISTS_FILTER_FLAGS(CXX)
- __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
+ __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.cxx "${SYMBOL}" "${FILES}" "${VARIABLE}" )
__CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(CXX)
else()
message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled")
@@ -92,7 +92,7 @@ endmacro()
macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}")
- set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
+ set(_CSE_SOURCE "/* */\n")
set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS})
if(CMAKE_REQUIRED_LINK_OPTIONS)
set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS
@@ -113,17 +113,17 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
set(CMAKE_SYMBOL_EXISTS_INCLUDES)
endif()
foreach(FILE ${FILES})
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
+ string(APPEND _CSE_SOURCE
"#include <${FILE}>\n")
endforeach()
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+ string(APPEND _CSE_SOURCE "
int main(int argc, char** argv)
{
(void)argv;")
set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];")
if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$")
# The SYMBOL has a legal macro name. Test whether it exists as a macro.
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+ string(APPEND _CSE_SOURCE "
#ifndef ${SYMBOL}
${_CSE_CHECK_NON_MACRO}
#else
@@ -132,22 +132,18 @@ int main(int argc, char** argv)
#endif")
else()
# The SYMBOL cannot be a macro (e.g., a template function).
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+ string(APPEND _CSE_SOURCE "
${_CSE_CHECK_NON_MACRO}")
endif()
- string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+ string(APPEND _CSE_SOURCE "
}")
unset(_CSE_CHECK_NON_MACRO)
- configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
- "${SOURCEFILE}" @ONLY)
-
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_START "Looking for ${SYMBOL}")
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- "${SOURCEFILE}"
+ SOURCE_FROM_VAR "${SOURCEFILE}" _CSE_SOURCE
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_SYMBOL_EXISTS_LINK_OPTIONS}
${CHECK_SYMBOL_EXISTS_LIBS}
@@ -164,7 +160,7 @@ int main(int argc, char** argv)
"Determining if the ${SYMBOL} "
"exist passed with the following output:\n"
"${OUTPUT}\nFile ${SOURCEFILE}:\n"
- "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
+ "${_CSE_SOURCE}\n")
else()
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_FAIL "not found")
@@ -174,9 +170,9 @@ int main(int argc, char** argv)
"Determining if the ${SYMBOL} "
"exist failed with the following output:\n"
"${OUTPUT}\nFile ${SOURCEFILE}:\n"
- "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
+ "${_CSE_SOURCE}\n")
endif()
- unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
+ unset(_CSE_SOURCE)
endif()
endmacro()
diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake
index 602170c14..b14ab0692 100644
--- a/Modules/CheckTypeSize.cmake
+++ b/Modules/CheckTypeSize.cmake
@@ -104,9 +104,9 @@ function(__check_type_size_impl type var map builtin language)
# Perform language check
if(language STREQUAL "C")
- set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c)
+ set(src ${var}.c)
elseif(language STREQUAL "CXX")
- set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.cpp)
+ set(src ${var}.cpp)
else()
message(FATAL_ERROR "Unknown language:\n ${language}\nSupported languages: C, CXX.\n")
endif()
@@ -142,8 +142,9 @@ function(__check_type_size_impl type var map builtin language)
# Perform the check.
set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin)
- configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY)
- try_compile(HAVE_${var} ${CMAKE_BINARY_DIR} ${src}
+ file(READ ${__check_type_size_dir}/CheckTypeSize.c.in src_content)
+ string(CONFIGURE "${src_content}" src_content @ONLY)
+ try_compile(HAVE_${var} SOURCE_FROM_VAR "${src}" src_content
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}
LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}
@@ -209,9 +210,8 @@ function(__check_type_size_impl type var map builtin language)
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_FAIL "failed")
endif()
- file(READ ${src} content)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${content}\n\n")
+ "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${src_content}\n\n")
set(${var} "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown")
file(REMOVE ${map})
endif()
diff --git a/Modules/CheckVariableExists.cmake b/Modules/CheckVariableExists.cmake
index 7420124f4..5dc344124 100644
--- a/Modules/CheckVariableExists.cmake
+++ b/Modules/CheckVariableExists.cmake
@@ -62,8 +62,7 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE)
set(CHECK_VARIABLE_EXISTS_ADD_LIBRARIES)
endif()
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/CheckVariableExists.c
+ SOURCES ${CMAKE_ROOT}/Modules/CheckVariableExists.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_VARIABLE_EXISTS_ADD_LINK_OPTIONS}
${CHECK_VARIABLE_EXISTS_ADD_LIBRARIES}
diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake
index 219897e4e..d9929f1f0 100644
--- a/Modules/Compiler/Clang-CUDA.cmake
+++ b/Modules/Compiler/Clang-CUDA.cmake
@@ -35,6 +35,10 @@ set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static")
set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "cudadevrt;cudart")
set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "")
+# Clang doesn't support CUDA device LTO
+set(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE NO)
+set(_CMAKE_CUDA_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+
if(UNIX)
list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl")
endif()
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index df115d3aa..4f9af3719 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -80,7 +80,7 @@ else()
set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
endif()
- if(ANDROID AND NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL "22")
+ if(ANDROID AND CMAKE_ANDROID_NDK_VERSION VERSION_LESS "22")
# https://github.com/android-ndk/ndk/issues/242
set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold")
endif()
@@ -255,6 +255,7 @@ macro(__compiler_clang_cxx_standards lang)
cxx_std_17
cxx_std_20
cxx_std_23
+ cxx_std_26
)
_record_compiler_features(${lang} "" CMAKE_${lang}_COMPILE_FEATURES)
endmacro()
diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake
index 6c15735e7..3f0ef1f35 100644
--- a/Modules/Compiler/IAR-CXX.cmake
+++ b/Modules/Compiler/IAR-CXX.cmake
@@ -22,9 +22,9 @@ if(NOT CMAKE_IAR_CXX_FLAG)
set(_CMAKE_IAR_MODERNCXX_LIST 14 17)
if(${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} IN_LIST _CMAKE_IAR_MODERNCXX_LIST OR
("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM" AND ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} EQUAL 98))
- string(PREPEND CMAKE_CXX_FLAGS "--c++ ")
+ set(CMAKE_IAR_CXX_FLAG --c++)
else()
- string(PREPEND CMAKE_CXX_FLAGS "--eec++ ")
+ set(CMAKE_IAR_CXX_FLAG --eec++)
endif()
unset(_CMAKE_IAR_MODERNCXX_LIST)
diff --git a/Modules/Compiler/IntelLLVM-FindBinUtils.cmake b/Modules/Compiler/IntelLLVM-FindBinUtils.cmake
new file mode 100644
index 000000000..c5b1ee63d
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-FindBinUtils.cmake
@@ -0,0 +1,45 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+ message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+# Ubuntu:
+# * /usr/bin/llvm-ar-9
+# * /usr/bin/llvm-ranlib-9
+string(REGEX MATCH "^([0-9]+)" __version_x
+ "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+# Debian:
+# * /usr/bin/llvm-ar-4.0
+# * /usr/bin/llvm-ranlib-4.0
+string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y
+ "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+# Try to find tools in the IntelLLVM Clang tools directory
+get_filename_component(__intel_llvm_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+get_filename_component(__intel_llvm_hint_1 "${__intel_llvm_hint_1}/../bin-llvm" REALPATH)
+
+get_filename_component(__intel_llvm_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+set(__intel_llvm_hints ${__intel_llvm_hint_1} ${__intel_llvm_hint_2})
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x_y}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar"
+ HINTS ${__intel_llvm_hints}
+ NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH
+ DOC "LLVM archiver"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x_y}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib"
+ HINTS ${__intel_llvm_hints}
+ NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH
+ DOC "Generate index for LLVM archive"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB)
diff --git a/Modules/Compiler/IntelLLVM.cmake b/Modules/Compiler/IntelLLVM.cmake
index c5800dc94..30de1a982 100644
--- a/Modules/Compiler/IntelLLVM.cmake
+++ b/Modules/Compiler/IntelLLVM.cmake
@@ -15,6 +15,15 @@ set(__pch_header_CXX "c++-header")
set(__pch_header_OBJC "objective-c-header")
set(__pch_header_OBJCXX "objective-c++-header")
+# Variables that are common across front-end variants
+macro(__compiler_intel_llvm_common lang)
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>")
+endmacro()
+
if(CMAKE_HOST_WIN32)
# MSVC-like
macro(__compiler_intel_llvm lang)
@@ -24,6 +33,9 @@ if(CMAKE_HOST_WIN32)
set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch)
set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX")
endif()
+ __compiler_intel_llvm_common(${lang})
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-Qipo")
+ set(CMAKE_${lang}_LINK_OPTIONS_IPO "-Qipo")
endmacro()
else()
# GNU-like
@@ -61,12 +73,9 @@ else()
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP)
- set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
- set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
- set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
- set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>")
+ __compiler_intel_llvm_common(${lang})
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-ipo")
+ set(CMAKE_${lang}_LINK_OPTIONS_IPO "-ipo")
set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake
index 75165fda4..212f6d195 100644
--- a/Modules/Compiler/MSVC-CXX.cmake
+++ b/Modules/Compiler/MSVC-CXX.cmake
@@ -72,7 +72,20 @@ elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
cxx_std_17
cxx_std_20
cxx_std_23
+ cxx_std_26
)
_record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES)
endmacro()
endif()
+
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.34")
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+ string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
+ "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> <SOURCE> -nologo -TP"
+ " -showIncludes"
+ " -scanDependencies <DYNDEP_FILE>"
+ " -Fo<OBJECT>")
+ set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT "msvc")
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "msvc")
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
+endif ()
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index e07d15202..c8dcd2a19 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -48,6 +48,13 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE)
endif()
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2)
+ set(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_CUDA_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+ set(CMAKE_CUDA_DEVICE_LINK_OPTIONS_IPO " -dlto")
+endif()
+
if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE)
set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC)
@@ -61,6 +68,7 @@ if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG")
string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG")
endif()
+
set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared)
set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=)
@@ -132,15 +140,19 @@ else()
endif()
-# FIXME: investigate use of --options-file.
-# Tell Makefile generator that nvcc does not support @<rspfile> syntax.
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
-
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0")
set(CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ")
set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
endif()
+if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0")
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+else()
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
+endif()
+
__compiler_check_default_language_standard(CUDA 6.0 03)
diff --git a/Modules/Compiler/Tasking-ASM.cmake b/Modules/Compiler/Tasking-ASM.cmake
new file mode 100644
index 000000000..19bce191f
--- /dev/null
+++ b/Modules/Compiler/Tasking-ASM.cmake
@@ -0,0 +1,7 @@
+include(Compiler/Tasking)
+
+set(CMAKE_ASM_OUTPUT_EXTENSION ".o")
+set(CMAKE_ASM_OUTPUT_EXTENSION_REPLACE 1)
+
+set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
+set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS S;s;asm;msa)
diff --git a/Modules/Compiler/Tasking-C.cmake b/Modules/Compiler/Tasking-C.cmake
new file mode 100644
index 000000000..0ea3cd2ff
--- /dev/null
+++ b/Modules/Compiler/Tasking-C.cmake
@@ -0,0 +1,47 @@
+include(Compiler/Tasking)
+__compiler_tasking(C)
+
+set(CMAKE_C90_STANDARD_COMPILE_OPTION "--iso=90" "--strict")
+set(CMAKE_C90_EXTENSION_COMPILE_OPTION "--iso=90" " ")
+
+set(CMAKE_C99_STANDARD_COMPILE_OPTION "--iso=99" "--strict")
+set(CMAKE_C99_EXTENSION_COMPILE_OPTION "--iso=99" " ")
+
+set(CMAKE_C11_STANDARD_COMPILE_OPTION "--iso=11" "--strict")
+set(CMAKE_C11_EXTENSION_COMPILE_OPTION "--iso=11" " ")
+
+if(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "TriCore")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(C 10.1 11)
+ else()
+ __compiler_check_default_language_standard(C 6.3 11)
+ endif()
+elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "ARM")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(C 10.1 11)
+ elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore")
+ __compiler_check_default_language_standard(C 6.3 11)
+ else()
+ __compiler_check_default_language_standard(C 6.0 11)
+ endif()
+elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "MCS")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(C 10.1 11)
+ elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore")
+ __compiler_check_default_language_standard(C 6.3 11)
+ else()
+ __compiler_check_default_language_standard(C 3.3 11)
+ endif()
+elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "ARC")
+ __compiler_check_default_language_standard(C 10.1 11)
+elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "8051")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(C 10.1 11)
+ elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore")
+ __compiler_check_default_language_standard(C 6.3 11)
+ else()
+ __compiler_check_default_language_standard(C 7.2 89)
+ endif()
+elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "PCP")
+ __compiler_check_default_language_standard(C 6.3 11)
+endif()
diff --git a/Modules/Compiler/Tasking-CXX.cmake b/Modules/Compiler/Tasking-CXX.cmake
new file mode 100644
index 000000000..635104c1d
--- /dev/null
+++ b/Modules/Compiler/Tasking-CXX.cmake
@@ -0,0 +1,31 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+include(Compiler/Tasking)
+__compiler_tasking(CXX)
+
+set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "--c++=03" "--strict")
+set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "--iso=03" " ")
+
+set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "--c++=11" "--strict")
+set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "--c++=11" " ")
+
+set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "--c++=14" "--strict")
+set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "--c++=14" " ")
+
+if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "TriCore")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(CXX 10.1 14)
+ else()
+ __compiler_check_default_language_standard(CXX 6.3 14)
+ endif()
+elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "ARM")
+ if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode")
+ __compiler_check_default_language_standard(CXX 10.1 14)
+ elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore")
+ __compiler_check_default_language_standard(CXX 6.3 14)
+ else()
+ __compiler_check_default_language_standard(CXX 6.0 14)
+ endif()
+else()
+ message(FATAL_ERROR "CXX is not supported with the ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} architecture.")
+endif()
diff --git a/Modules/Compiler/Tasking-DetermineCompiler.cmake b/Modules/Compiler/Tasking-DetermineCompiler.cmake
new file mode 100644
index 000000000..a40be199a
--- /dev/null
+++ b/Modules/Compiler/Tasking-DetermineCompiler.cmake
@@ -0,0 +1,10 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+set(_compiler_id_pp_test "defined(__TASKING__)")
+
+set(_compiler_id_version_compute "
+ # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__VERSION__/1000)
+ # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__VERSION__ % 100)")
+
+string(APPEND _compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__VERSION__)")
diff --git a/Modules/Compiler/Tasking-FindBinUtils.cmake b/Modules/Compiler/Tasking-FindBinUtils.cmake
new file mode 100644
index 000000000..eab31d720
--- /dev/null
+++ b/Modules/Compiler/Tasking-FindBinUtils.cmake
@@ -0,0 +1,18 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# Find the archiver for the compiler architecture, which is always in the same
+# directory as the compiler.
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+ message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+get_filename_component(__tasking_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR
+ NAMES artc ararm armcs ar51 ararc arpcp
+ HINTS ${__tasking_hints}
+ NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH
+ DOC "Tasking Archiver"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
diff --git a/Modules/Compiler/Tasking.cmake b/Modules/Compiler/Tasking.cmake
new file mode 100644
index 000000000..5bf066eef
--- /dev/null
+++ b/Modules/Compiler/Tasking.cmake
@@ -0,0 +1,54 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# This module is shared by multiple languages; use include blocker.
+if(_Tasking_CMAKE_LOADED)
+ return()
+endif()
+set(_Tasking_CMAKE_LOADED TRUE)
+include(Compiler/CMakeCommonCompilerMacros)
+
+set(CMAKE_EXECUTABLE_SUFFIX ".elf")
+set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+set(BUILD_SHARED_LIBS FALSE CACHE BOOL "")
+set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+set(CMAKE_LINK_SEARCH_START_STATIC TRUE)
+
+if(NOT CMAKE_TASKING_TOOLSET)
+ set(CMAKE_TASKING_TOOLSET "Standalone")
+endif()
+
+macro(__compiler_tasking lang)
+
+ set(CMAKE_${lang}_VERBOSE_FLAG "-v")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "--pic")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl" " ")
+ set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-f ")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "--dep-file=<DEP_FILE>")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "--warning-as-errors")
+
+ string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
+ string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -O0 -g")
+ string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O2 -t4 -DNDEBUG")
+ string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O2 -t2 -DNDEBUG")
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -t2 -g -DNDEBUG")
+
+ set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_${lang}_COMPILER_AR}\" -r <TARGET> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND "\"${CMAKE_${lang}_COMPILER_AR}\" -r <TARGET> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_FINISH "")
+
+ set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -cs <SOURCE> -o <ASSEMBLY_SOURCE>")
+ set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -Ep <SOURCE> > <PREPROCESSED_SOURCE>")
+
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
+ if(CMAKE_${lang}_COMPILER_ARG1)
+ separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
+ unset(_COMPILER_ARGS)
+ endif()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-Ep" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
+
+endmacro()
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 995265803..22a25bd1f 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -1840,7 +1840,11 @@ function(_ep_get_build_command
else()
set(cmd "${CMAKE_COMMAND}")
endif()
- set(args --build ".")
+ if(step STREQUAL "INSTALL")
+ set(args --install ".")
+ else()
+ set(args --build ".")
+ endif()
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_isMultiConfig)
if (CMAKE_CFG_INTDIR AND
@@ -1862,9 +1866,6 @@ function(_ep_get_build_command
endif()
list(APPEND args --config ${config})
endif()
- if(step STREQUAL "INSTALL")
- list(APPEND args --target install)
- endif()
# But for "TEST" drive the project with corresponding "ctest".
if("x${step}x" STREQUAL "xTESTx")
string(REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}")
@@ -3832,6 +3833,19 @@ function(_ep_add_install_command name)
set(uses_terminal "")
endif()
+ # With BUILD_ALWAYS+BUILD_BYPRODUCTS, Ninja restats the
+ # build step outputs and may not consider this step to
+ # be out-of-date. Explicitly mark it out-of-date too.
+ get_property(build_always
+ TARGET ${name}
+ PROPERTY _EP_BUILD_ALWAYS
+ )
+ if(build_always)
+ set(always 1)
+ else()
+ set(always 0)
+ endif()
+
set(__cmdQuoted)
foreach(__item IN LISTS cmd)
string(APPEND __cmdQuoted " [==[${__item}]==]")
@@ -3842,6 +3856,7 @@ function(_ep_add_install_command name)
COMMAND ${__cmdQuoted}
WORKING_DIRECTORY \${binary_dir}
DEPENDEES build
+ ALWAYS \${always}
${log}
${uses_terminal}
)"
diff --git a/Modules/ExternalProject/gitupdate.cmake.in b/Modules/ExternalProject/gitupdate.cmake.in
index 7896f6297..50f016706 100644
--- a/Modules/ExternalProject/gitupdate.cmake.in
+++ b/Modules/ExternalProject/gitupdate.cmake.in
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5)
function(get_hash_for_ref ref out_var err_var)
execute_process(
- COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^0"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git rev-parse "${ref}^0"
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE ref_hash
@@ -27,7 +27,7 @@ endif()
execute_process(
- COMMAND "@git_EXECUTABLE@" show-ref "@git_tag@"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git show-ref "@git_tag@"
WORKING_DIRECTORY "@work_dir@"
OUTPUT_VARIABLE show_ref_output
)
@@ -95,7 +95,7 @@ endif()
if(fetch_required)
message(VERBOSE "Fetching latest from the remote @git_remote_name@")
execute_process(
- COMMAND "@git_EXECUTABLE@" fetch --tags --force "@git_remote_name@"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@"
WORKING_DIRECTORY "@work_dir@"
COMMAND_ERROR_IS_FATAL ANY
)
@@ -112,7 +112,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$")
# We can't if we aren't already on a branch and we shouldn't if that local
# branch isn't tracking the one we want to checkout.
execute_process(
- COMMAND "@git_EXECUTABLE@" symbolic-ref -q HEAD
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git symbolic-ref -q HEAD
WORKING_DIRECTORY "@work_dir@"
OUTPUT_VARIABLE current_branch
OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -128,7 +128,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$")
else()
execute_process(
- COMMAND "@git_EXECUTABLE@" for-each-ref "--format=%(upstream:short)" "${current_branch}"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git for-each-ref "--format=%(upstream:short)" "${current_branch}"
WORKING_DIRECTORY "@work_dir@"
OUTPUT_VARIABLE upstream_branch
OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -151,7 +151,7 @@ endif()
# Check if stash is needed
execute_process(
- COMMAND "@git_EXECUTABLE@" status --porcelain
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git status --porcelain
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE repo_status
@@ -165,7 +165,7 @@ string(LENGTH "${repo_status}" need_stash)
# rebase or checkout without losing those changes permanently
if(need_stash)
execute_process(
- COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git stash save @git_stash_save_options@
WORKING_DIRECTORY "@work_dir@"
COMMAND_ERROR_IS_FATAL ANY
)
@@ -173,13 +173,13 @@ endif()
if(git_update_strategy STREQUAL "CHECKOUT")
execute_process(
- COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
WORKING_DIRECTORY "@work_dir@"
COMMAND_ERROR_IS_FATAL ANY
)
else()
execute_process(
- COMMAND "@git_EXECUTABLE@" rebase "${checkout_name}"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase "${checkout_name}"
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE rebase_output
@@ -188,7 +188,7 @@ else()
if(error_code)
# Rebase failed, undo the rebase attempt before continuing
execute_process(
- COMMAND "@git_EXECUTABLE@" rebase --abort
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase --abort
WORKING_DIRECTORY "@work_dir@"
)
@@ -196,7 +196,7 @@ else()
# Not allowed to do a checkout as a fallback, so cannot proceed
if(need_stash)
execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
WORKING_DIRECTORY "@work_dir@"
)
endif()
@@ -218,7 +218,7 @@ else()
message(WARNING "Rebase failed, output has been saved to ${error_log_file}"
"\nFalling back to checkout, previous commit tagged as ${tag_name}")
execute_process(
- COMMAND "@git_EXECUTABLE@" tag -a
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git tag -a
-m "ExternalProject attempting to move from here to ${checkout_name}"
${tag_name}
WORKING_DIRECTORY "@work_dir@"
@@ -226,7 +226,7 @@ else()
)
execute_process(
- COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}"
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
WORKING_DIRECTORY "@work_dir@"
COMMAND_ERROR_IS_FATAL ANY
)
@@ -236,29 +236,29 @@ endif()
if(need_stash)
# Put back the stashed changes
execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
)
if(error_code)
# Stash pop --index failed: Try again dropping the index
execute_process(
- COMMAND "@git_EXECUTABLE@" reset --hard --quiet
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet
WORKING_DIRECTORY "@work_dir@"
)
execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --quiet
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --quiet
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
)
if(error_code)
# Stash pop failed: Restore previous state.
execute_process(
- COMMAND "@git_EXECUTABLE@" reset --hard --quiet ${head_sha}
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet ${head_sha}
WORKING_DIRECTORY "@work_dir@"
)
execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
WORKING_DIRECTORY "@work_dir@"
)
message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'."
@@ -270,7 +270,7 @@ endif()
set(init_submodules "@init_submodules@")
if(init_submodules)
execute_process(
- COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git submodule update @git_submodules_recurse@ --init @git_submodules@
WORKING_DIRECTORY "@work_dir@"
COMMAND_ERROR_IS_FATAL ANY
)
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 995e69a93..ac3918cf8 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -111,6 +111,7 @@ Commands
FetchContent_Declare(
<name>
<contentOptions>...
+ [SYSTEM]
[OVERRIDE_FIND_PACKAGE |
FIND_PACKAGE_ARGS args...]
)
@@ -229,6 +230,16 @@ Commands
to intercept any direct call to :command:`find_package`, except if that
call contains the ``BYPASS_PROVIDER`` option.
+ .. versionadded:: 3.25
+
+ ``SYSTEM``
+ If the ``SYSTEM`` argument is provided, targets created by
+ the dependency will have their :prop_tgt:`SYSTEM` property
+ set to true when populated by :command:`FetchContent_MakeAvailable`.
+ The entries in their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
+ will be treated as ``SYSTEM`` include directories when
+ compiling consumers.
+
.. command:: FetchContent_MakeAvailable
.. versionadded:: 3.14
@@ -884,9 +895,10 @@ Overriding Where To Find CMakeLists.txt
If the sub-project's ``CMakeLists.txt`` file is not at the top level of its
source tree, the ``SOURCE_SUBDIR`` option can be used to tell ``FetchContent``
-where to find it. The following example shows how to use that option and
+where to find it. The following example shows how to use that option, and
it also sets a variable which is meaningful to the subproject before pulling
-it into the main build:
+it into the main build (set as an ``INTERNAL`` cache variable to avoid
+problems with policy :policy:`CMP0077`):
.. code-block:: cmake
@@ -897,7 +909,7 @@ it into the main build:
GIT_TAG ae50d9b9902526efd6c7a1907d09739f959c6297 # v3.15.0
SOURCE_SUBDIR cmake
)
- set(protobuf_BUILD_TESTS OFF)
+ set(protobuf_BUILD_TESTS OFF CACHE INTERNAL "")
FetchContent_MakeAvailable(protobuf)
Complex Dependency Hierarchies
@@ -1972,13 +1984,17 @@ macro(FetchContent_MakeAvailable)
if("${__cmake_contentDetails}" STREQUAL "")
message(FATAL_ERROR "No details have been set for content: ${__cmake_contentName}")
endif()
- cmake_parse_arguments(__cmake_arg "" "SOURCE_SUBDIR" "" ${__cmake_contentDetails})
+ cmake_parse_arguments(__cmake_arg "SYSTEM" "SOURCE_SUBDIR" "" ${__cmake_contentDetails})
if(NOT "${__cmake_arg_SOURCE_SUBDIR}" STREQUAL "")
string(APPEND __cmake_srcdir "/${__cmake_arg_SOURCE_SUBDIR}")
endif()
if(EXISTS ${__cmake_srcdir}/CMakeLists.txt)
- add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR})
+ if (__cmake_arg_SYSTEM)
+ add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR} SYSTEM)
+ else()
+ add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR})
+ endif()
endif()
unset(__cmake_srcdir)
diff --git a/Modules/FindAVIFile.cmake b/Modules/FindAVIFile.cmake
index 96554405d..d63b707ac 100644
--- a/Modules/FindAVIFile.cmake
+++ b/Modules/FindAVIFile.cmake
@@ -7,7 +7,7 @@ FindAVIFile
Locate AVIFILE library and include paths
-AVIFILE (http://avifile.sourceforge.net/) is a set of libraries for
+AVIFILE (https://avifile.sourceforge.net/) is a set of libraries for
i386 machines to use various AVI codecs. Support is limited beyond
Linux. Windows provides native AVI support, and so doesn't need this
library. This module defines
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 7a381af9b..7af101700 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -12,7 +12,7 @@ This module finds an installed Fortran library that implements the
At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled.
-.. _`BLAS linear-algebra interface`: http://www.netlib.org/blas/
+.. _`BLAS linear-algebra interface`: https://netlib.org/blas/
Input Variables
^^^^^^^^^^^^^^^
@@ -35,6 +35,12 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a BLAS library first
and if one is found that is preferred
+``BLA_PKGCONFIG_BLAS``
+ .. versionadded:: 3.25
+
+ If set, the ``pkg-config`` method will look for this module name instead of
+ just ``blas``.
+
``BLA_SIZEOF_INTEGER``
.. versionadded:: 3.22
@@ -273,8 +279,11 @@ endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
if(BLA_PREFER_PKGCONFIG)
+ if(NOT BLA_PKGCONFIG_BLAS)
+ set(BLA_PKGCONFIG_BLAS "blas")
+ endif()
find_package(PkgConfig QUIET)
- pkg_check_modules(PKGC_BLAS QUIET blas)
+ pkg_check_modules(PKGC_BLAS QUIET ${BLA_PKGCONFIG_BLAS})
if(PKGC_BLAS_FOUND)
set(BLAS_FOUND ${PKGC_BLAS_FOUND})
set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
diff --git a/Modules/FindBacktrace.cmake b/Modules/FindBacktrace.cmake
index 3d8ce884a..46b62d2e3 100644
--- a/Modules/FindBacktrace.cmake
+++ b/Modules/FindBacktrace.cmake
@@ -5,7 +5,7 @@
FindBacktrace
-------------
-Find provider for `backtrace(3) <http://man7.org/linux/man-pages/man3/backtrace.3.html>`__.
+Find provider for `backtrace(3) <https://man7.org/linux/man-pages/man3/backtrace.3.html>`__.
Checks if OS supports ``backtrace(3)`` via either ``libc`` or custom library.
This module defines the following variables:
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index af5f79821..470111fa6 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -799,7 +799,9 @@ if(NOT "${CUDA_TOOLKIT_ROOT_DIR}" STREQUAL "${CUDA_TOOLKIT_ROOT_DIR_INTERNAL}")
unset(CUDA_VERSION CACHE)
endif()
-if(NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}")
+# If CUDA_TOOLKIT_TARGET_DIR exists, check if it has changed.
+if(DEFINED CUDA_TOOLKIT_TARGET_DIR
+ AND NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}")
cuda_unset_include_and_libraries()
endif()
diff --git a/Modules/FindCUDA/select_compute_arch.cmake b/Modules/FindCUDA/select_compute_arch.cmake
index a35b3f8ff..5fad33703 100644
--- a/Modules/FindCUDA/select_compute_arch.cmake
+++ b/Modules/FindCUDA/select_compute_arch.cmake
@@ -135,10 +135,10 @@ function(CUDA_DETECT_INSTALLED_GPUS OUT_VARIABLE)
"}\n")
if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language
- try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file}
+ try_run(run_result compile_result SOURCES ${file}
RUN_OUTPUT_VARIABLE compute_capabilities)
else()
- try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file}
+ try_run(run_result compile_result SOURCES ${file}
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CUDA_INCLUDE_DIRS}"
LINK_LIBRARIES ${CUDA_LIBRARIES}
RUN_OUTPUT_VARIABLE compute_capabilities)
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 5f83ccc3d..94c86e9f1 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -109,6 +109,7 @@ of the following libraries that are part of the CUDAToolkit:
- :ref:`CUDA Runtime Library<cuda_toolkit_rt_lib>`
- :ref:`CUDA Driver Library<cuda_toolkit_driver_lib>`
- :ref:`cuBLAS<cuda_toolkit_cuBLAS>`
+- :ref:`cuFile<cuda_toolkit_cuFile>`
- :ref:`cuFFT<cuda_toolkit_cuFFT>`
- :ref:`cuRAND<cuda_toolkit_cuRAND>`
- :ref:`cuSOLVER<cuda_toolkit_cuSOLVER>`
@@ -119,8 +120,10 @@ of the following libraries that are part of the CUDAToolkit:
- :ref:`nvGRAPH<cuda_toolkit_nvGRAPH>`
- :ref:`nvJPEG<cuda_toolkit_nvJPEG>`
- :ref:`nvidia-ML<cuda_toolkit_nvML>`
+- :ref:`nvPTX Compiler<cuda_toolkit_nvptx>`
- :ref:`nvRTC<cuda_toolkit_nvRTC>`
- :ref:`nvToolsExt<cuda_toolkit_nvToolsExt>`
+- :ref:`nvtx3<cuda_toolkit_nvtx3>`
- :ref:`OpenCL<cuda_toolkit_opencl>`
- :ref:`cuLIBOS<cuda_toolkit_cuLIBOS>`
@@ -163,6 +166,22 @@ Targets Created:
- ``CUDA::cublasLt`` starting in CUDA 10.1
- ``CUDA::cublasLt_static`` starting in CUDA 10.1
+.. _`cuda_toolkit_cuFile`:
+
+cuFile
+""""""
+
+.. versionadded:: 3.25
+
+The NVIDIA GPUDirect Storage `cuFile <https://docs.nvidia.com/cuda/cufile-api/index.html>`_ library.
+
+Targets Created:
+
+- ``CUDA::cuFile`` starting in CUDA 11.4
+- ``CUDA::cuFile_static`` starting in CUDA 11.4
+- ``CUDA::cuFile_rdma`` starting in CUDA 11.4
+- ``CUDA::cuFile_rdma_static`` starting in CUDA 11.4
+
.. _`cuda_toolkit_cuFFT`:
cuFFT
@@ -333,6 +352,22 @@ Targets Created:
- ``CUDA::nvjpeg``
- ``CUDA::nvjpeg_static``
+.. _`cuda_toolkit_nvPTX`:
+
+nvPTX Compiler
+""""""""""""""
+
+.. versionadded:: 3.25
+
+The `nvPTX <https://docs.nvidia.com/cuda/ptx-compiler-api/index.html>`_ (PTX Compilation) library.
+The PTX Compiler APIs are a set of APIs which can be used to compile a PTX program into GPU assembly code.
+Introduced in CUDA 11.1
+This is a static library only.
+
+Targets Created:
+
+- ``CUDA::nvptxcompiler_static`` starting in CUDA 11.1
+
.. _`cuda_toolkit_nvRTC`:
nvRTC
@@ -362,6 +397,8 @@ Targets Created:
nvToolsExt
""""""""""
+.. deprecated:: 3.25 With CUDA 10.0+, use :ref:`nvtx3 <cuda_toolkit_nvtx3>`.
+
The `NVIDIA Tools Extension <https://docs.nvidia.com/gameworks/content/gameworkslibrary/nvtx/nvidia_tools_extension_library_nvtx.htm>`_.
This is a shared library only.
@@ -369,6 +406,20 @@ Targets Created:
- ``CUDA::nvToolsExt``
+.. _`cuda_toolkit_nvtx3`:
+
+nvtx3
+"""""
+
+.. versionadded:: 3.25
+
+The header-only `NVIDIA Tools Extension Library <https://nvidia.github.io/NVTX/doxygen/index.html>`_.
+Introduced in CUDA 10.0.
+
+Targets created:
+
+- ``CUDA::nvtx3``
+
.. _`cuda_toolkit_opencl`:
OpenCL
@@ -942,6 +993,14 @@ if(CUDAToolkit_FOUND)
_CUDAToolkit_find_and_add_import_lib(cublas_static DEPS culibos)
endif()
+ if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.4)
+ _CUDAToolkit_find_and_add_import_lib(cuFile DEPS culibos)
+ _CUDAToolkit_find_and_add_import_lib(cuFile_static DEPS culibos)
+
+ _CUDAToolkit_find_and_add_import_lib(cuFile_rdma DEPS cuFile culibos)
+ _CUDAToolkit_find_and_add_import_lib(cuFile_rdma_static DEPS cuFile_static culibos)
+ endif()
+
# cuFFTW depends on cuFFT
_CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft)
_CUDAToolkit_find_and_add_import_lib(cufftw_static DEPS cufft_static)
@@ -998,6 +1057,12 @@ if(CUDAToolkit_FOUND)
endif()
_CUDAToolkit_find_and_add_import_lib(nvrtc DEPS cuda_driver)
+ 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)
+ endif()
+ endif()
_CUDAToolkit_find_and_add_import_lib(nvml ALT nvidia-ml nvml)
@@ -1014,6 +1079,21 @@ if(CUDAToolkit_FOUND)
endif()
_CUDAToolkit_find_and_add_import_lib(nvToolsExt ALT nvToolsExt64)
+ if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.0)
+ # nvToolsExt is deprecated since nvtx3 introduction.
+ # Warn only if the project requires a sufficiently new CMake to make migration possible.
+ if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_GREATER_EQUAL 3.25)
+ set_property(TARGET CUDA::nvToolsExt PROPERTY DEPRECATION "nvToolsExt has been superseded by nvtx3 since CUDA 10.0 and CMake 3.25. Use CUDA::nvtx3 and include <nvtx3/nvToolsExt.h> instead.")
+ endif()
+
+ # Header-only variant. Uses dlopen().
+ if(NOT TARGET CUDA::nvtx3)
+ add_library(CUDA::nvtx3 INTERFACE IMPORTED)
+ target_include_directories(CUDA::nvtx3 SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}")
+ target_link_libraries(CUDA::nvtx3 INTERFACE ${CMAKE_DL_LIBS})
+ endif()
+ endif()
+
_CUDAToolkit_find_and_add_import_lib(OpenCL)
endif()
diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake
index e37d22591..acb87dc60 100644
--- a/Modules/FindCURL.cmake
+++ b/Modules/FindCURL.cmake
@@ -72,6 +72,8 @@ if(NOT CURL_NO_CURL_CMAKE)
# can print what we found and return.
if(CURL_FOUND)
find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE)
+ # The upstream curl package sets CURL_VERSION, not CURL_VERSION_STRING.
+ set(CURL_VERSION_STRING "${CURL_VERSION}")
return()
endif()
endif()
@@ -80,7 +82,6 @@ find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(PC_CURL QUIET libcurl)
if(PC_CURL_FOUND)
- set(CURL_VERSION_STRING ${PC_CURL_VERSION})
pkg_get_variable(CURL_SUPPORTED_PROTOCOLS libcurl supported_protocols)
pkg_get_variable(CURL_SUPPORTED_FEATURES libcurl supported_features)
endif()
@@ -120,7 +121,7 @@ if(NOT CURL_LIBRARY)
select_library_configurations(CURL)
endif()
-if(CURL_INCLUDE_DIR AND NOT CURL_VERSION_STRING)
+if(CURL_INCLUDE_DIR)
foreach(_curl_version_header curlver.h curl.h)
if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
diff --git a/Modules/FindCoin3D.cmake b/Modules/FindCoin3D.cmake
index 301e70bd6..5910ad1e4 100644
--- a/Modules/FindCoin3D.cmake
+++ b/Modules/FindCoin3D.cmake
@@ -31,11 +31,11 @@ if (WIN32)
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/include"
)
- find_library(COIN3D_LIBRARY_DEBUG coin2d
+ find_library(COIN3D_LIBRARY_DEBUG NAMES coin2d coin4d
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/lib"
)
- find_library(COIN3D_LIBRARY_RELEASE coin2
+ find_library(COIN3D_LIBRARY_RELEASE NAMES coin2 coin4
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/lib"
)
diff --git a/Modules/FindCxxTest.cmake b/Modules/FindCxxTest.cmake
index 3fc0e938a..04f8b5944 100644
--- a/Modules/FindCxxTest.cmake
+++ b/Modules/FindCxxTest.cmake
@@ -9,7 +9,7 @@ Find CxxTest unit testing framework.
Find the CxxTest suite and declare a helper macro for creating unit
tests and integrating them with CTest. For more details on CxxTest
-see http://cxxtest.tigris.org
+see https://cxxtest.com
INPUT Variables
diff --git a/Modules/FindDCMTK.cmake b/Modules/FindDCMTK.cmake
index b2e00dffd..0154a059a 100644
--- a/Modules/FindDCMTK.cmake
+++ b/Modules/FindDCMTK.cmake
@@ -18,15 +18,16 @@ Compatibility
^^^^^^^^^^^^^
This module is able to find a version of DCMTK that does or does not export
-a *DCMTKConfig.cmake* file. It applies a two step process:
+a ``DCMTKConfig.cmake`` file. It applies a two step process:
-* Step 1: Attempt to find DCMTK version providing a *DCMTKConfig.cmake* file.
-* Step 2: If step 1 failed, rely on *FindDCMTK.cmake* to set `DCMTK_*` variables details below.
+* Step 1: Attempt to find DCMTK version providing a ``DCMTKConfig.cmake`` file.
+* Step 2: If step 1 failed, rely on ``FindDCMTK.cmake`` to set ``DCMTK_*``
+ variables details below.
`Recent DCMTK
-<http://git.dcmtk.org/web?p=dcmtk.git;a=commit;h=662ae187c493c6b9a73dd5e3875372cebd0c11fe>`_
-provides a *DCMTKConfig.cmake* :manual:`package configuration file
+<https://git.dcmtk.org/?p=dcmtk.git;a=commit;h=662ae187c493c6b9a73dd5e3875372cebd0c11fe>`_
+provides a ``DCMTKConfig.cmake`` :manual:`package configuration file
<cmake-packages(7)>`. To exclusively use the package configuration file
(recommended when possible), pass the `NO_MODULE` option to
:command:`find_package`. For example, `find_package(DCMTK NO_MODULE)`.
diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake
index c8e5e3154..7f726ffa0 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -8,7 +8,7 @@ FindDevIL
This module locates the developer's image library.
-http://openil.sourceforge.net/
+https://openil.sourceforge.net/
IMPORTED Targets
^^^^^^^^^^^^^^^^
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 4a16e316a..ef9801eb2 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -5,14 +5,14 @@
FindDoxygen
-----------
-Doxygen is a documentation generation tool (see http://www.doxygen.org).
+Doxygen is a documentation generation tool (see https://www.doxygen.nl).
This module looks for Doxygen and some optional tools it supports:
``dot``
- `Graphviz <http://graphviz.org>`_ ``dot`` utility used to render various
+ `Graphviz <https://graphviz.org>`_ ``dot`` utility used to render various
graphs.
``mscgen``
- `Message Chart Generator <http://www.mcternan.me.uk/mscgen/>`_ utility used
+ `Message Chart Generator <https://www.mcternan.me.uk/mscgen/>`_ utility used
by Doxygen's ``\msc`` and ``\mscfile`` commands.
``dia``
`Dia <https://wiki.gnome.org/Apps/Dia>`_ the diagram editor used by Doxygen's
@@ -91,7 +91,7 @@ Functions
base point. Note also that Doxygen's default behavior is to strip the working
directory from relative paths in the generated documentation (see the
``STRIP_FROM_PATH`` `Doxygen config option
- <http://www.doxygen.org/manual/config.html>`_ for details).
+ <https://www.doxygen.nl/manual/config.html>`_ for details).
If provided, the optional ``comment`` will be passed as the ``COMMENT`` for
the :command:`add_custom_target` command used to create the custom target
@@ -117,7 +117,7 @@ Functions
variables before calling ``doxygen_add_docs()``. Any variable with a name of
the form ``DOXYGEN_<tag>`` will have its value substituted for the
corresponding ``<tag>`` configuration option in the ``Doxyfile``. See the
- `Doxygen documentation <http://www.doxygen.org/manual/config.html>`_ for the
+ `Doxygen documentation <https://www.doxygen.nl/manual/config.html>`_ for the
full list of supported configuration options.
Some of Doxygen's defaults are overridden to provide more appropriate
@@ -432,9 +432,44 @@ endif()
# or use something like homebrew.
# ============== End OSX stuff ================
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
#
# Find Doxygen...
#
+function(_Doxygen_get_version doxy_version result_var doxy_path)
+ execute_process(
+ COMMAND "${doxy_path}" --version
+ OUTPUT_VARIABLE full_doxygen_version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE version_result
+ )
+
+ # Ignore any commit hashes, etc.
+ string(REGEX MATCH [[^[0-9]+\.[0-9]+\.[0-9]+]] sem_doxygen_version "${full_doxygen_version}")
+
+ set(${result_var} ${version_result} PARENT_SCOPE)
+ set(${doxy_version} ${sem_doxygen_version} PARENT_SCOPE)
+endfunction()
+
+function(_Doxygen_version_validator version_match doxy_path)
+ if(NOT DEFINED Doxygen_FIND_VERSION)
+ set(${is_valid_version} TRUE PARENT_SCOPE)
+ else()
+ _Doxygen_get_version(candidate_version version_result "${doxy_path}")
+
+ if(version_result)
+ message(DEBUG "Unable to determine candidate doxygen version at ${doxy_path}: ${version_result}")
+ endif()
+
+ find_package_check_version("${candidate_version}" valid_doxy_version
+ HANDLE_VERSION_RANGE
+ )
+
+ set(${version_match} "${valid_doxy_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
macro(_Doxygen_find_doxygen)
find_program(
DOXYGEN_EXECUTABLE
@@ -445,17 +480,14 @@ macro(_Doxygen_find_doxygen)
/Applications/Doxygen.app/Contents/MacOS
/Applications/Utilities/Doxygen.app/Contents/Resources
/Applications/Utilities/Doxygen.app/Contents/MacOS
- DOC "Doxygen documentation generation tool (http://www.doxygen.org)"
+ DOC "Doxygen documentation generation tool (https://www.doxygen.nl)"
+ VALIDATOR _Doxygen_version_validator
)
mark_as_advanced(DOXYGEN_EXECUTABLE)
if(DOXYGEN_EXECUTABLE)
- execute_process(
- COMMAND "${DOXYGEN_EXECUTABLE}" --version
- OUTPUT_VARIABLE DOXYGEN_VERSION
- OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE _Doxygen_version_result
- )
+ _Doxygen_get_version(DOXYGEN_VERSION _Doxygen_version_result "${DOXYGEN_EXECUTABLE}")
+
if(_Doxygen_version_result)
message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}")
endif()
@@ -642,11 +674,11 @@ endforeach()
unset(_comp)
# Verify find results
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(
Doxygen
REQUIRED_VARS DOXYGEN_EXECUTABLE
VERSION_VAR DOXYGEN_VERSION
+ HANDLE_VERSION_RANGE
HANDLE_COMPONENTS
)
@@ -919,7 +951,7 @@ doxygen_add_docs() for target ${targetName}")
if(NOT DEFINED DOXYGEN_HAVE_DOT)
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot
# tool is available from the path. This tool is part of Graphviz (see:
- # http://www.graphviz.org/), a graph visualization toolkit from AT&T
+ # https://www.graphviz.org/), a graph visualization toolkit from AT&T
# and Lucent Bell Labs. The other options in this section have no
# effect if this option is set to NO.
# Doxygen's default value is: NO.
diff --git a/Modules/FindGDAL.cmake b/Modules/FindGDAL.cmake
index 5237e1513..e6eac30fb 100644
--- a/Modules/FindGDAL.cmake
+++ b/Modules/FindGDAL.cmake
@@ -160,7 +160,7 @@ unset(_gdal_version)
unset(_gdal_versions)
find_library(GDAL_LIBRARY
- NAMES ${_gdal_lib} ${_gdal_libnames} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL
+ NAMES ${_gdal_lib} ${_gdal_libnames} gdal gdald gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL
HINTS
ENV GDAL_DIR
ENV GDAL_ROOT
diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake
index b9ebe08bd..bfde40b3d 100644
--- a/Modules/FindGLEW.cmake
+++ b/Modules/FindGLEW.cmake
@@ -63,11 +63,36 @@ This module defines the following variables:
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
find_package(GLEW CONFIG QUIET)
if(GLEW_FOUND)
find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG)
+ get_target_property(GLEW_INCLUDE_DIRS GLEW::GLEW INTERFACE_INCLUDE_DIRECTORIES)
+ set(GLEW_INCLUDE_DIR ${GLEW_INCLUDE_DIRS})
+ get_target_property(_GLEW_DEFS GLEW::GLEW INTERFACE_COMPILE_DEFINITIONS)
+ if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
+ get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_LOCATION_DEBUG)
+ get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_LOCATION_RELEASE)
+ else()
+ get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_IMPLIB_DEBUG)
+ get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_IMPLIB_RELEASE)
+ endif()
+ get_target_property(_GLEW_LINK_INTERFACE GLEW::GLEW IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) # same for debug and release
+ list(APPEND GLEW_LIBRARIES ${_GLEW_LINK_INTERFACE})
+ list(APPEND GLEW_LIBRARY ${_GLEW_LINK_INTERFACE})
+ select_library_configurations(GLEW)
+ if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
+ set(GLEW_STATIC_LIBRARIES ${GLEW_LIBRARIES})
+ else()
+ set(GLEW_SHARED_LIBRARIES ${GLEW_LIBRARIES})
+ endif()
+ unset(_GLEW_DEFS)
+ unset(_GLEW_LINK_INTERFACE)
+ unset(GLEW_LIBRARY)
+ unset(GLEW_LIBRARY_DEBUG)
+ unset(GLEW_LIBRARY_RELEASE)
return()
endif()
@@ -171,8 +196,6 @@ find_library(GLEW_STATIC_LIBRARY_DEBUG
set(CMAKE_FIND_LIBRARY_SUFFIXES ${__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES})
unset(__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES)
-include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
-
select_library_configurations(GLEW_SHARED)
select_library_configurations(GLEW_STATIC)
diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake
index 320ddad2e..09403bc11 100644
--- a/Modules/FindGLUT.cmake
+++ b/Modules/FindGLUT.cmake
@@ -67,83 +67,41 @@ The following variables may also be provided, for backwards compatibility:
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-function(_add_glut_target_simple)
- if(TARGET GLUT::GLUT)
- return()
- endif()
- add_library(GLUT::GLUT INTERFACE IMPORTED)
- if(GLUT_INCLUDE_DIRS)
- target_include_directories(GLUT::GLUT SYSTEM
- INTERFACE "${GLUT_INCLUDE_DIRS}")
- endif()
- if(GLUT_LIBRARIES)
- target_link_libraries(GLUT::GLUT INTERFACE ${GLUT_LIBRARIES})
- endif()
- if(GLUT_LIBRARY_DIRS)
- target_link_directories(GLUT::GLUT INTERFACE ${GLUT_LIBRARY_DIRS})
- endif()
- if(GLUT_LDFLAGS)
- target_link_options(GLUT::GLUT INTERFACE ${GLUT_LDFLAGS})
- endif()
- if(GLUT_CFLAGS)
- separate_arguments(GLUT_CFLAGS_SPLIT UNIX_COMMAND "${GLUT_CFLAGS}")
- target_compile_options(GLUT::GLUT INTERFACE ${GLUT_CFLAGS_SPLIT})
- endif()
-
- set_property(TARGET GLUT::GLUT APPEND PROPERTY
- IMPORTED_LOCATION "${GLUT_glut_LIBRARY}")
-endfunction()
-
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
- # Tell pkg-config not to strip any -I flags to make sure GLUT_INCLUDE_DIRS
- # will be defined.
- if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS})
- set(_pkgconfig_allow_system_cflags_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}")
- else()
- unset(_pkgconfig_allow_system_cflags_old)
- endif()
- set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1)
- pkg_check_modules(GLUT QUIET glut)
- if(DEFINED _pkgconfig_allow_system_cflags_old)
- set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} "${_pkgconfig_allow_system_cflags_old}")
- unset(_pkgconfig_allow_system_cflags_old)
- else()
- unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS})
- endif()
- if(NOT GLUT_FOUND)
- pkg_check_modules(GLUT QUIET freeglut)
- endif()
- if(GLUT_FOUND)
- # GLUT_INCLUDE_DIRS is now the official result variable, but
- # older versions of CMake only provided GLUT_INCLUDE_DIR.
- set(GLUT_INCLUDE_DIR "${GLUT_INCLUDE_DIRS}")
- _add_glut_target_simple()
- FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND)
- return()
+ pkg_check_modules(PC_GLUT QUIET glut)
+ if(NOT PC_GLUT_FOUND)
+ pkg_check_modules(PC_GLUT QUIET freeglut)
endif()
endif()
if(WIN32)
find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h
- PATHS ${GLUT_ROOT_PATH}/include )
+ PATHS ${GLUT_ROOT_PATH}/include
+ HINTS ${PC_GLUT_INCLUDE_DIRS})
mark_as_advanced(GLUT_INCLUDE_DIR)
find_library( GLUT_glut_LIBRARY_RELEASE NAMES freeglut glut glut32
PATHS
${OPENGL_LIBRARY_DIR}
${GLUT_ROOT_PATH}/Release
+ HINTS
+ ${PC_GLUT_LIBRARY_DIRS}
)
+# N.B. As the pkg-config cannot distinguish between release and debug libraries,
+# assume that their hint was the both Debug and Release library.
find_library( GLUT_glut_LIBRARY_DEBUG NAMES freeglutd
PATHS
${OPENGL_LIBRARY_DIR}
${GLUT_ROOT_PATH}/Debug
+ HINTS
+ ${PC_GLUT_LIBRARY_DIRS}
)
mark_as_advanced(GLUT_glut_LIBRARY_RELEASE GLUT_glut_LIBRARY_DEBUG)
select_library_configurations(GLUT_glut)
elseif(APPLE)
- find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
+ find_path(GLUT_INCLUDE_DIR glut.h PATHS ${OPENGL_LIBRARY_DIR} HINTS ${PC_GLUT_INCLUDE_DIRS})
mark_as_advanced(GLUT_INCLUDE_DIR)
- find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX")
+ find_library(GLUT_glut_LIBRARY GLUT HINTS ${PC_GLUT_LIBRARY_DIRS} DOC "GLUT library for OSX")
find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX")
mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY)
@@ -192,18 +150,24 @@ else()
endif ()
find_path( GLUT_INCLUDE_DIR GL/glut.h
+ PATHS
/usr/include/GL
/usr/openwin/share/include
/usr/openwin/include
/opt/graphics/OpenGL/include
/opt/graphics/OpenGL/contrib/libglut
${_GLUT_INC_DIR}
+ HINTS
+ ${PC_GLUT_INCLUDE_DIRS}
)
mark_as_advanced(GLUT_INCLUDE_DIR)
find_library( GLUT_glut_LIBRARY glut
+ PATHS
/usr/openwin/lib
${_GLUT_glut_LIB_DIR}
+ HINTS
+ ${PC_GLUT_LIBRARY_DIRS}
)
mark_as_advanced(GLUT_glut_LIBRARY)
diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake
index 00bfc29c8..46348768e 100644
--- a/Modules/FindGTK2.cmake
+++ b/Modules/FindGTK2.cmake
@@ -313,6 +313,7 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
/usr/openwin/lib
/sw/lib
/opt/local/lib
+ /opt/homebrew/lib
/usr/pkg/lib
/usr/pkg/include/glib
$ENV{GTKMM_BASEPATH}/include
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 40ed9a92c..d662a7dd4 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -238,7 +238,7 @@ function(_HDF5_test_regular_compiler_C success version is_parallel)
" fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n"
" return 0;\n"
"}")
- try_compile(${success} ${scratch_directory} ${test_file}
+ try_compile(${success} SOURCES ${test_file}
COPY_FILE ${scratch_directory}/compiler_has_h5_c
)
endif()
@@ -286,7 +286,7 @@ function(_HDF5_test_regular_compiler_CXX success version is_parallel)
" H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n"
" return 0;\n"
"}")
- try_compile(${success} ${scratch_directory} ${test_file}
+ try_compile(${success} SOURCES ${test_file}
COPY_FILE ${scratch_directory}/compiler_has_h5_cxx
)
endif()
@@ -323,7 +323,7 @@ function(_HDF5_test_regular_compiler_Fortran success is_parallel)
" call h5open_f(error)\n"
" call h5close_f(error)\n"
"end\n")
- try_compile(${success} ${scratch_directory} ${test_file})
+ try_compile(${success} SOURCES ${test_file})
if(${success})
execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig
OUTPUT_VARIABLE config_output
diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake
index 91dcba5a8..b4f4d7134 100644
--- a/Modules/FindICU.cmake
+++ b/Modules/FindICU.cmake
@@ -254,13 +254,6 @@ function(_ICU_FIND)
set("${component_found}" ON)
set("${component_found_compat}" ON)
list(APPEND ICU_LIBRARY "${${component_cache}}")
- endif()
- mark_as_advanced("${component_found}")
- mark_as_advanced("${component_found_compat}")
- set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
- set("${component_found}" "${${component_found}}" PARENT_SCOPE)
- set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
- if(component_found OR component_found_compat)
if (ICU_FIND_REQUIRED_${component})
list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}")
else()
@@ -274,6 +267,11 @@ function(_ICU_FIND)
list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)")
endif()
endif()
+ mark_as_advanced("${component_found}")
+ mark_as_advanced("${component_found_compat}")
+ set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
+ set("${component_found}" "${${component_found}}" PARENT_SCOPE)
+ set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
endforeach()
set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE)
set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE)
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index b08b359b8..1eecb1cbd 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -12,7 +12,7 @@ This module finds an installed Fortran library that implements the
At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled.
-.. _`LAPACK linear-algebra interface`: http://www.netlib.org/lapack/
+.. _`LAPACK linear-algebra interface`: https://netlib.org/lapack/
Input Variables
^^^^^^^^^^^^^^^
@@ -35,6 +35,13 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a LAPACK library first
and if one is found that is preferred
+``BLA_PKGCONFIG_LAPACK``
+ .. versionadded:: 3.25
+
+ If set, the ``pkg-config`` method will look for this module name instead of
+ just ``lapack``.
+
+
``BLA_SIZEOF_INTEGER``
.. versionadded:: 3.22
@@ -278,8 +285,11 @@ endif()
# Search with pkg-config if specified
if(BLA_PREFER_PKGCONFIG)
+ if(NOT BLA_PKGCONFIG_LAPACK)
+ set(BLA_PKGCONFIG_LAPACK "lapack")
+ endif()
find_package(PkgConfig QUIET)
- pkg_check_modules(PKGC_LAPACK QUIET lapack)
+ pkg_check_modules(PKGC_LAPACK QUIET ${BLA_PKGCONFIG_LAPACK})
if(PKGC_LAPACK_FOUND)
set(LAPACK_FOUND TRUE)
set(LAPACK_LIBRARIES "${PKGC_LAPACK_LINK_LIBRARIES}")
diff --git a/Modules/FindLTTngUST.cmake b/Modules/FindLTTngUST.cmake
index a70a418f4..eaace4fa7 100644
--- a/Modules/FindLTTngUST.cmake
+++ b/Modules/FindLTTngUST.cmake
@@ -8,7 +8,7 @@ FindLTTngUST
.. versionadded:: 3.6
Find
-`Linux Trace Toolkit Next Generation (LTTng-UST) <http://lttng.org/>`__ library.
+`Linux Trace Toolkit Next Generation (LTTng-UST) <https://lttng.org/>`__ library.
Imported target
^^^^^^^^^^^^^^^
diff --git a/Modules/FindLibArchive.cmake b/Modules/FindLibArchive.cmake
index 08078a295..9d3ac13f1 100644
--- a/Modules/FindLibArchive.cmake
+++ b/Modules/FindLibArchive.cmake
@@ -26,6 +26,9 @@ The module defines the following ``IMPORTED`` targets:
.. versionadded:: 3.6
Support for new libarchive 3.2 version string format.
+.. versionadded:: 3.17
+ Provides an imported target.
+
#]=======================================================================]
find_path(LibArchive_INCLUDE_DIR
diff --git a/Modules/FindMFC.cmake b/Modules/FindMFC.cmake
index b8ca71bb8..2d5de8914 100644
--- a/Modules/FindMFC.cmake
+++ b/Modules/FindMFC.cmake
@@ -29,23 +29,19 @@ endif()
if(MFC_ATTEMPT_TRY_COMPILE)
if(NOT DEFINED MFC_HAVE_MFC)
set(CHECK_INCLUDE_FILE_VAR "afxwin.h")
- configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx)
+ file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in _CIF_SOURCE_CONTENT)
+ string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT)
message(CHECK_START "Looking for MFC")
# Try both shared and static as the root project may have set the /MT flag
try_compile(MFC_HAVE_MFC
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx
+ SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT
CMAKE_FLAGS
-DCMAKE_MFC_FLAG:STRING=2
-DCOMPILE_DEFINITIONS:STRING=-D_AFXDLL
OUTPUT_VARIABLE OUTPUT)
if(NOT MFC_HAVE_MFC)
- configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx)
try_compile(MFC_HAVE_MFC
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx
+ SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT
CMAKE_FLAGS
-DCMAKE_MFC_FLAG:STRING=1
OUTPUT_VARIABLE OUTPUT)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index bca0c105e..e15be916f 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -391,11 +391,11 @@ function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE)
# library that has invalid or missing version information there would be warning
# messages emitted by ld.so in the compiler output. In either case, we'll treat
# the output as invalid.
- if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found")
+ if(WRAPPER_OUTPUT MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found")
set(WRAPPER_RETURN 255)
endif()
# Ensure that no error output might be passed upwards.
- if(NOT WRAPPER_RETURN EQUAL 0)
+ if(NOT WRAPPER_RETURN EQUAL "0")
unset(WRAPPER_OUTPUT)
else()
# Strip leading whitespace
@@ -441,13 +441,13 @@ function (_MPI_interrogate_compiler LANG)
if(MSVC)
get_filename_component(_MPI_UNDERLAYING_COMPILER "${_MPI_UNDERLAYING_COMPILER}" NAME)
endif()
- if("${LANG}" STREQUAL "C")
+ if(LANG STREQUAL "C")
_MPI_env_set_ifnot(I_MPI_CC _MPI_UNDERLAYING_COMPILER)
_MPI_env_set_ifnot(MPICH_CC _MPI_UNDERLAYING_COMPILER)
- elseif("${LANG}" STREQUAL "CXX")
+ elseif(LANG STREQUAL "CXX")
_MPI_env_set_ifnot(I_MPI_CXX _MPI_UNDERLAYING_COMPILER)
_MPI_env_set_ifnot(MPICH_CXX _MPI_UNDERLAYING_COMPILER)
- elseif("${LANG}" STREQUAL "Fortran")
+ elseif(LANG STREQUAL "Fortran")
_MPI_env_set_ifnot(I_MPI_FC _MPI_UNDERLAYING_COMPILER)
_MPI_env_set_ifnot(MPICH_FC _MPI_UNDERLAYING_COMPILER)
_MPI_env_set_ifnot(I_MPI_F77 _MPI_UNDERLAYING_COMPILER)
@@ -470,10 +470,10 @@ function (_MPI_interrogate_compiler LANG)
# or a newer version of LAM/MPI, and implies that -showme:link will also work.
# Open MPI also supports -show, but separates linker and compiler information
_MPI_check_compiler(${LANG} "-showme:compile" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
- if (MPI_COMPILER_RETURN EQUAL 0)
+ if (MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "-showme:link" MPI_LINK_CMDLINE MPI_COMPILER_RETURN)
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
unset(MPI_COMPILE_CMDLINE)
endif()
endif()
@@ -482,13 +482,13 @@ function (_MPI_interrogate_compiler LANG)
# For modern versions, both do the same as -show. However, for old versions, they do differ
# when called for mpicxx and mpif90 and it's necessary to use them over -show in order to find the
# removed MPI C++ bindings.
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "-compile-info" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
- if (MPI_COMPILER_RETURN EQUAL 0)
+ if (MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "-link-info" MPI_LINK_CMDLINE MPI_COMPILER_RETURN)
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
unset(MPI_COMPILE_CMDLINE)
endif()
endif()
@@ -496,18 +496,18 @@ function (_MPI_interrogate_compiler LANG)
# Cray compiler wrappers come usually without a separate mpicc/c++/ftn, but offer
# --cray-print-opts=...
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "--cray-print-opts=cflags"
MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
- if (MPI_COMPILER_RETURN EQUAL 0)
+ if (MPI_COMPILER_RETURN EQUAL "0")
# Pass --no-as-needed so the mpi library is always linked. Otherwise, the
# Cray compiler wrapper puts an --as-needed flag around the mpi library,
# and it is not linked unless code directly refers to it.
_MPI_check_compiler(${LANG} "--no-as-needed;--cray-print-opts=libs"
MPI_LINK_CMDLINE MPI_COMPILER_RETURN)
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
unset(MPI_COMPILE_CMDLINE)
unset(MPI_LINK_CMDLINE)
endif()
@@ -516,24 +516,24 @@ function (_MPI_interrogate_compiler LANG)
# MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the
# -showme commands are more specialized.
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "-show" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
endif()
# Older versions of LAM/MPI have "-showme". Open MPI also supports this.
# Unknown to MPICH, MVAPICH and Intel MPI.
- if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ if (NOT MPI_COMPILER_RETURN EQUAL "0")
_MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
endif()
- if (MPI_COMPILER_RETURN EQUAL 0 AND DEFINED MPI_COMPILE_CMDLINE)
+ if (MPI_COMPILER_RETURN EQUAL "0" AND DEFINED MPI_COMPILE_CMDLINE)
# Intel MPI can be run with -compchk or I_MPI_CHECK_COMPILER set to 1.
# In this case, -show will be prepended with a line to the compiler checker. This is a script that performs
# compatibility checks and returns a non-zero exit code together with an error if something fails.
# It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64).
# The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler.
# NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler.
- if("${MPI_COMPILE_CMDLINE}" MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)")
+ if(MPI_COMPILE_CMDLINE MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)")
# Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag.
unset(COMPILER_CHECKER_OUTPUT)
execute_process(
@@ -542,7 +542,7 @@ function (_MPI_interrogate_compiler LANG)
ERROR_VARIABLE COMPILER_CHECKER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE MPI_COMPILER_RETURN)
# If it returned a non-zero value, the check below will fail and cause the interrogation to be aborted.
- if(NOT MPI_COMPILER_RETURN EQUAL 0)
+ if(NOT MPI_COMPILER_RETURN EQUAL "0")
if(NOT MPI_FIND_QUIETLY)
message(STATUS "Intel MPI compiler check failed: ${COMPILER_CHECKER_OUTPUT}")
endif()
@@ -554,13 +554,13 @@ function (_MPI_interrogate_compiler LANG)
endif()
# Revert changes to the environment made previously
- if("${LANG}" STREQUAL "C")
+ if(LANG STREQUAL "C")
_MPI_env_unset_ifnot(I_MPI_CC)
_MPI_env_unset_ifnot(MPICH_CC)
- elseif("${LANG}" STREQUAL "CXX")
+ elseif(LANG STREQUAL "CXX")
_MPI_env_unset_ifnot(I_MPI_CXX)
_MPI_env_unset_ifnot(MPICH_CXX)
- elseif("${LANG}" STREQUAL "Fortran")
+ elseif(LANG STREQUAL "Fortran")
_MPI_env_unset_ifnot(I_MPI_FC)
_MPI_env_unset_ifnot(MPICH_FC)
_MPI_env_unset_ifnot(I_MPI_F77)
@@ -572,7 +572,7 @@ function (_MPI_interrogate_compiler LANG)
_MPI_env_unset_ifnot(I_MPI_DEBUG_INFO_STRIP)
_MPI_env_unset_ifnot(I_MPI_FORT_BIND)
- if (NOT (MPI_COMPILER_RETURN EQUAL 0) OR NOT (DEFINED MPI_COMPILE_CMDLINE))
+ if (NOT (MPI_COMPILER_RETURN EQUAL "0") OR NOT (DEFINED MPI_COMPILE_CMDLINE))
# Cannot interrogate this compiler, so exit.
set(MPI_${LANG}_WRAPPER_FOUND FALSE PARENT_SCOPE)
return()
@@ -613,13 +613,13 @@ function (_MPI_interrogate_compiler LANG)
if(UNIX)
# At this point, we obtained some output from a compiler wrapper that works.
# We'll now try to parse it into variables with meaning to us.
- if("${LANG}" STREQUAL "Fortran")
+ if(LANG STREQUAL "Fortran")
# If MPICH (and derivates) didn't recognize the Fortran compiler include flag during configuration,
# they'll return a set of three commands, consisting out of a symlink command for mpif.h,
# the actual compiler command and deletion of the created symlink.
# Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate
# this output into an additional include directory and then drop it from the output.
- if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h")
+ if(MPI_COMPILE_CMDLINE MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h")
get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY)
string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}")
string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}")
@@ -651,7 +651,7 @@ function (_MPI_interrogate_compiler LANG)
# produce inconsistent results with the regularly flags.
# Similarly, aliasing flags do not belong into our flag array.
# Also strip out `-framework` flags.
- if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)")
+ if(NOT _MPI_COMPILE_OPTION MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)")
list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}")
endif()
endforeach()
@@ -673,7 +673,7 @@ function (_MPI_interrogate_compiler LANG)
foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS)
string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}")
string(REPLACE "\"" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}")
- if(NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*")
+ if(NOT _MPI_COMPILE_DEFINITION MATCHES "^_FORTIFY_SOURCE.*")
list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}")
endif()
endforeach()
@@ -788,7 +788,7 @@ function (_MPI_interrogate_compiler LANG)
# decide how to link it based on file type, not based on a prefix like 'lib'.
set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX)
- if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}"))
+ if(NOT (CMAKE_IMPORT_LIBRARY_SUFFIX STREQUAL CMAKE_STATIC_LIBRARY_SUFFIX))
string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}")
endif()
else()
@@ -804,7 +804,7 @@ function (_MPI_interrogate_compiler LANG)
if(_MPI_LIB_NAME_TEST STREQUAL "")
string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY)
- if(NOT "${_MPI_LIB_PATH}" STREQUAL "")
+ if(NOT _MPI_LIB_PATH STREQUAL "")
list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}")
else()
list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}")
@@ -845,7 +845,7 @@ function (_MPI_interrogate_compiler LANG)
foreach(_MPI_LINK_DIRECTORY IN LISTS MPI_LINK_DIRECTORIES_LEFTOVER)
file(TO_NATIVE_PATH "${_MPI_LINK_DIRECTORY}" _MPI_LINK_DIRECTORY_ACTUAL)
string(FIND "${_MPI_LINK_DIRECTORY_ACTUAL}" " " _MPI_LINK_DIRECTORY_CONTAINS_SPACE)
- if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL -1)
+ if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL "-1")
set(_MPI_LINK_DIRECTORY_ACTUAL "\"${_MPI_LINK_DIRECTORY_ACTUAL}\"")
endif()
if(MPI_LINK_FLAGS_WORK)
@@ -871,7 +871,7 @@ function (_MPI_interrogate_compiler LANG)
# MPI might require pthread to work. The above mechanism wouldn't detect it, but we need to
# link it in that case. -lpthread is covered by the normal library treatment on the other hand.
- if("${MPI_COMPILE_CMDLINE}" MATCHES "-pthread")
+ if(MPI_COMPILE_CMDLINE MATCHES "-pthread")
list(APPEND MPI_COMPILE_OPTIONS_WORK "-pthread")
if(MPI_LINK_FLAGS_WORK)
string(APPEND MPI_LINK_FLAGS_WORK " -pthread")
@@ -918,10 +918,10 @@ function(_MPI_guess_settings LANG)
# The environment variables MSMPI_INC and MSMPILIB32/64 are the only ways of locating the MSMPI_SDK,
# which is installed separately from the runtime. Thus it's possible to have mpiexec but not MPI headers
# or import libraries and vice versa.
- if(NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MSMPI")
+ if(NOT MPI_GUESS_LIBRARY_NAME OR MPI_GUESS_LIBRARY_NAME STREQUAL "MSMPI")
# We first attempt to locate the msmpi.lib. Should be find it, we'll assume that the MPI present is indeed
# Microsoft MPI.
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ if(CMAKE_SIZEOF_VOID_P EQUAL "8")
file(TO_CMAKE_PATH "$ENV{MSMPI_LIB64}" MPI_MSMPI_LIB_PATH)
file(TO_CMAKE_PATH "$ENV{MSMPI_INC}/x64" MPI_MSMPI_INC_PATH_EXTRA)
else()
@@ -975,9 +975,9 @@ function(_MPI_guess_settings LANG)
# Our strategy is now to locate all libraries, but enter msmpifec into the LIB_NAMES array.
# Should this not be adequate it's a straightforward way for a user to change the LIB_NAMES array and
# have his library found. Still, this should not be necessary outside of exceptional cases, as reasoned.
- if ("${LANG}" STREQUAL "Fortran")
+ if (LANG STREQUAL "Fortran")
set(MPI_MSMPI_CALLINGCONVS c)
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
+ if(CMAKE_SIZEOF_VOID_P EQUAL "4")
list(APPEND MPI_MSMPI_CALLINGCONVS s)
endif()
foreach(mpistrlenpos IN ITEMS e m)
@@ -1025,7 +1025,7 @@ function(_MPI_guess_settings LANG)
# At this point there's not many MPIs that we could still consider.
# OpenMPI 1.6.x and below supported Windows, but these ship compiler wrappers that still work.
# The only other relevant MPI implementation without a wrapper is MPICH2, which had Windows support in 1.4.1p1 and older.
- if(NOT MPI_GUESS_FOUND AND (NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MPICH2"))
+ if(NOT MPI_GUESS_FOUND AND (NOT MPI_GUESS_LIBRARY_NAME OR MPI_GUESS_LIBRARY_NAME STREQUAL "MPICH2"))
set(MPI_MPICH_PREFIX_PATHS
"$ENV{ProgramW6432}/MPICH2/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/../lib"
@@ -1042,7 +1042,7 @@ function(_MPI_guess_settings LANG)
set(MPI_MPICH_LIB_NAMES "mpi")
# If MPI-2 C++ bindings are requested, we need to locate cxx.lib as well.
# Otherwise, MPICH_SKIP_MPICXX will be defined and these bindings aren't needed.
- if("${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX)
+ if(LANG STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX)
find_library(MPI_cxx_LIBRARY
NAMES cxx
HINTS ${MPI_MPICH_PREFIX_PATHS})
@@ -1055,7 +1055,7 @@ function(_MPI_guess_settings LANG)
# fmpich2s.lib would be useful for Compaq Visual Fortran, fmpich2g.lib has to be used with GNU g77 and is also
# provided in the form of an .a archive for MinGW and Cygwin. From our perspective, fmpich2.lib is the only one
# we need to try, and if it doesn't work with the given Fortran compiler we'd find out later on during validation
- elseif("${LANG}" STREQUAL "Fortran")
+ elseif(LANG STREQUAL "Fortran")
find_library(MPI_fmpich2_LIBRARY
NAMES fmpich2
HINTS ${MPI_MPICH_PREFIX_PATHS})
@@ -1103,7 +1103,7 @@ function(_MPI_guess_settings LANG)
endfunction()
function(_MPI_adjust_compile_definitions LANG)
- if("${LANG}" STREQUAL "CXX")
+ if(LANG STREQUAL "CXX")
# To disable the C++ bindings, we need to pass some definitions since the mpi.h header has to deal with both C and C++
# bindings in MPI-2.
if(MPI_CXX_SKIP_MPICXX AND NOT MPI_${LANG}_COMPILE_DEFINITIONS MATCHES "SKIP_MPICXX")
@@ -1119,7 +1119,7 @@ endfunction()
macro(_MPI_assemble_libraries LANG)
set(MPI_${LANG}_LIBRARIES "")
# Only for libraries do we need to check whether the compiler's linking stage is separate.
- if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS_IMPLICIT)
+ if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER OR NOT MPI_${LANG}_WORKS_IMPLICIT)
foreach(mpilib IN LISTS MPI_${LANG}_LIB_NAMES)
list(APPEND MPI_${LANG}_LIBRARIES ${MPI_${mpilib}_LIBRARY})
endforeach()
@@ -1131,7 +1131,7 @@ macro(_MPI_assemble_include_dirs LANG)
${MPI_${LANG}_COMPILER_INCLUDE_DIRS}
${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS}
)
- if("${LANG}" MATCHES "(C|CXX)")
+ if(LANG MATCHES "^(C|CXX)$")
if(MPI_${LANG}_HEADER_DIR)
list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}")
endif()
@@ -1156,7 +1156,7 @@ macro(_MPI_split_include_dirs LANG)
# We try to find the headers/modules among those paths (and system paths)
# For C/C++, we just need to have a look for mpi.h.
- if("${LANG}" MATCHES "(C|CXX)")
+ if(LANG MATCHES "^(C|CXX)$")
find_path(MPI_${LANG}_HEADER_DIR "mpi.h"
HINTS
${MPI_${LANG}_COMPILER_INCLUDE_DIRS}
@@ -1171,7 +1171,7 @@ macro(_MPI_split_include_dirs LANG)
# any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI
# only provides Fortran 77 and - if mpi.f90 is built - potentially
# a Fortran 90 module.
- elseif("${LANG}" STREQUAL "Fortran")
+ elseif(LANG STREQUAL "Fortran")
find_path(MPI_${LANG}_F77_HEADER_DIR "mpif.h"
HINTS
${MPI_${LANG}_COMPILER_INCLUDE_DIRS}
@@ -1238,28 +1238,30 @@ function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRE
set(SRC_DIR "${CMAKE_ROOT}/Modules/FindMPI")
set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI/${MPI_TEST_FILE_NAME}_${LANG}.bin")
unset(MPI_TEST_COMPILE_DEFINITIONS)
- if("${LANG}" STREQUAL "Fortran")
- if("${MODE}" STREQUAL "F90_MODULE")
+ if(LANG STREQUAL "Fortran")
+ if(MODE STREQUAL "F90_MODULE")
set(MPI_Fortran_INCLUDE_LINE "use mpi\n implicit none")
- elseif("${MODE}" STREQUAL "F08_MODULE")
+ elseif(MODE STREQUAL "F08_MODULE")
set(MPI_Fortran_INCLUDE_LINE "use mpi_f08\n implicit none")
else() # F77 header
set(MPI_Fortran_INCLUDE_LINE "implicit none\n include 'mpif.h'")
endif()
- configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" @ONLY)
- set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90")
- elseif("${LANG}" STREQUAL "CXX")
- configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" COPYONLY)
- set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp")
- if("${MODE}" STREQUAL "TEST_MPICXX")
+ file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" MPI_TEST_SOURCE_CONTENT)
+ string(CONFIGURE "${MPI_TEST_SOURCE_CONTENT}" MPI_TEST_SOURCE_CONTENT)
+ set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.f90")
+ elseif(LANG STREQUAL "CXX")
+ file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" MPI_TEST_SOURCE_CONTENT)
+ set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.cpp")
+ if(MODE STREQUAL "TEST_MPICXX")
set(MPI_TEST_COMPILE_DEFINITIONS TEST_MPI_MPICXX)
endif()
else() # C
- set(MPI_TEST_SOURCE_FILE "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c")
+ file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" MPI_TEST_SOURCE_CONTENT)
+ set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.c")
endif()
if(RUN_BINARY)
try_run(MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}
- "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}"
+ SOURCE_FROM_VAR "${MPI_TEST_SOURCE_FILE}" MPI_TEST_SOURCE_CONTENT
COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS}
LINK_LIBRARIES MPI::MPI_${LANG}
RUN_OUTPUT_VARIABLE MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}
@@ -1267,7 +1269,7 @@ function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRE
set(MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} "${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}" PARENT_SCOPE)
else()
try_compile(MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}
- "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}"
+ SOURCE_FROM_VAR "${MPI_TEST_SOURCE_FILE}" MPI_TEST_SOURCE_CONTENT
COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS}
LINK_LIBRARIES MPI::MPI_${LANG}
COPY_FILE "${BIN_FILE}"
@@ -1290,7 +1292,7 @@ macro(_MPI_check_lang_works LANG SUPPRESS_ERRORS)
# - *both*, the mpi module and 'mpif.h'
# Since older MPI standards (MPI-1) did not define anything but 'mpif.h', we need to check all three individually.
if( NOT MPI_${LANG}_WORKS )
- if("${LANG}" STREQUAL "Fortran")
+ if(LANG STREQUAL "Fortran")
set(MPI_Fortran_INTEGER_LINE "(kind=MPI_INTEGER_KIND)")
_MPI_try_staged_settings(${LANG} test_mpi F77_HEADER FALSE ${SUPPRESS_ERRORS})
_MPI_try_staged_settings(${LANG} test_mpi F90_MODULE FALSE ${SUPPRESS_ERRORS})
@@ -1339,11 +1341,11 @@ macro(MPI_search_mpi_prefix_folder PREFIX_FOLDER)
endmacro()
set(MPI_HINT_DIRS ${MPI_HOME} $ENV{MPI_HOME} $ENV{I_MPI_ROOT})
-if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
# SUSE Linux Enterprise Server stores its MPI implementations under /usr/lib64/mpi/gcc/<name>
# We enumerate the subfolders and append each as a prefix
MPI_search_mpi_prefix_folder("/usr/lib64/mpi/gcc")
-elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "FreeBSD")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "FreeBSD")
# FreeBSD ships mpich under the normal system paths - but available openmpi implementations
# will be found in /usr/local/mpi/<name>
MPI_search_mpi_prefix_folder("/usr/local/mpi")
@@ -1410,7 +1412,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES)
if(MPI_${LANG}_COMPILE_FLAGS)
separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}")
foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS)
- if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)")
+ if(_MPI_FLAG MATCHES "^ *-D([^ ]+)")
list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}")
else()
list(APPEND MPI_${LANG}_EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}")
@@ -1459,7 +1461,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
set(_MPI_FIND_${LANG} TRUE)
elseif( LANG IN_LIST MPI_FIND_COMPONENTS)
set(_MPI_FIND_${LANG} TRUE)
- elseif( "${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS )
+ elseif( LANG STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS )
set(_MPI_FIND_${LANG} TRUE)
else()
set(_MPI_FIND_${LANG} FALSE)
@@ -1471,7 +1473,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endif()
if(_MPI_FIND_${LANG})
- if( "${LANG}" STREQUAL "CXX" AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS )
+ if( LANG STREQUAL "CXX" AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS )
option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE)
mark_as_advanced(MPI_CXX_SKIP_MPICXX)
endif()
@@ -1493,7 +1495,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
set(MPI_${LANG}_TRIED_IMPLICIT TRUE)
endif()
- if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS)
+ if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER OR NOT MPI_${LANG}_WORKS)
set(MPI_${LANG}_WRAPPER_FOUND FALSE)
set(MPI_PINNED_COMPILER FALSE)
@@ -1529,7 +1531,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
DOC "MPI compiler for ${LANG}"
)
- if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}")
+ if(MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER)
set(MPI_PINNED_COMPILER TRUE)
# If we haven't made the implicit compiler test yet, perform it now.
@@ -1590,7 +1592,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
if(_MPI_PKG AND PKG_CONFIG_FOUND)
pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}")
- if("${MPI_${LANG}_PKG_FOUND}")
+ if(MPI_${LANG}_PKG_FOUND)
set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE)
set(MPI_${LANG}_INCLUDE_PATH ${MPI_${LANG}_PKG_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} include directories" FORCE)
set(MPI_${LANG}_LINK_FLAGS ${MPI_${LANG}_PKG_LDFLAGS} CACHE STRING "MPI ${LANG} linker flags" FORCE)
@@ -1611,10 +1613,10 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endif()
- if(NOT MPI_SKIP_GUESSING AND NOT "${MPI_${LANG}_PKG_FOUND}")
+ if(NOT MPI_SKIP_GUESSING AND NOT MPI_${LANG}_PKG_FOUND)
# For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the
# settings for C. An MPI distribution that is in this situation would be IBM Platform MPI.
- if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND)
+ if(LANG STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND)
set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_C_COMPILE_OPTIONS} CACHE STRING "MPI ${LANG} compilation options" )
set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_C_COMPILE_DEFINITIONS} CACHE STRING "MPI ${LANG} compilation definitions" )
set(MPI_${LANG}_COMPILER_INCLUDE_DIRS ${MPI_C_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} compiler wrapper include directories")
@@ -1628,7 +1630,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endif()
- if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}")
+ if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER)
_MPI_split_include_dirs(${LANG})
_MPI_assemble_include_dirs(${LANG})
else()
@@ -1665,7 +1667,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
# If we've found MPI, then we'll perform additional analysis: Determine the MPI version, MPI library version, supported
# MPI APIs (i.e. MPI-2 C++ bindings). For Fortran we also need to find specific parameters if we're under MPI-3.
if(MPI_${LANG}_WORKS)
- if("${LANG}" STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND)
+ if(LANG STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND)
if(NOT MPI_CXX_SKIP_MPICXX AND NOT MPI_CXX_VALIDATE_SKIP_MPICXX)
_MPI_try_staged_settings(${LANG} test_mpi MPICXX FALSE FALSE)
if(MPI_RESULT_${LANG}_test_mpi_MPICXX)
@@ -1689,7 +1691,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
# Fortran parameters, since those depend on the method of consumption.
# For C++, we can always use the C bindings, and should do so, since the C++ bindings do not exist in MPI-3
# whereas the C bindings do, and the C++ bindings never offered any feature advantage over their C counterparts.
- if("${LANG}" STREQUAL "Fortran")
+ if(LANG STREQUAL "Fortran")
if(MPI_${LANG}_HAVE_F08_MODULE)
set(MPI_${LANG}_HIGHEST_METHOD F08_MODULE)
elseif(MPI_${LANG}_HAVE_F90_MODULE)
@@ -1705,7 +1707,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
_MPI_try_staged_settings(${LANG} mpiver ${MPI_${LANG}_HIGHEST_METHOD} FALSE FALSE)
if(MPI_RESULT_${LANG}_mpiver_${MPI_${LANG}_HIGHEST_METHOD})
file(STRINGS ${MPI_BIN_FOLDER}/mpiver_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER")
- if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*")
+ if(_MPI_VERSION_STRING MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*")
set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}")
set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}")
@@ -1724,12 +1726,12 @@ foreach(LANG IN ITEMS C CXX Fortran)
_MPI_try_staged_settings(${LANG} fortranparam_mpi ${mpimethod} TRUE FALSE)
if(MPI_RESULT_${LANG}_fortranparam_mpi_${mpimethod} AND
NOT "${MPI_RUN_RESULT_${LANG}_fortranparam_mpi_${mpimethod}}" STREQUAL "FAILED_TO_RUN")
- if("${MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod}}" MATCHES
+ if(MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod} MATCHES
".*INFO:SUBARRAYS\\[ *([TF]) *\\]-ASYNCPROT\\[ *([TF]) *\\].*")
- if("${CMAKE_MATCH_1}" STREQUAL "T")
+ if(CMAKE_MATCH_1 STREQUAL "T")
set(MPI_${LANG}_${mpimethod}_SUBARRAYS TRUE)
endif()
- if("${CMAKE_MATCH_2}" STREQUAL "T")
+ if(CMAKE_MATCH_2 STREQUAL "T")
set(MPI_${LANG}_${mpimethod}_ASYNCPROT TRUE)
endif()
endif()
@@ -1744,7 +1746,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
# By the MPI-2 standard, MPI_VERSION and MPI_SUBVERSION are valid for both C and C++ bindings.
if(NOT DEFINED MPI_${LANG}_VERSION)
file(STRINGS ${MPI_BIN_FOLDER}/test_mpi_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER")
- if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*")
+ if(_MPI_VERSION_STRING MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*")
set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}")
set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}")
@@ -1764,7 +1766,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
if(MPI_DETERMINE_LIBRARY_VERSION AND NOT MPI_${LANG}_LIBRARY_VERSION_STRING)
_MPI_try_staged_settings(${LANG} libver_mpi ${MPI_${LANG}_HIGHEST_METHOD} TRUE FALSE)
if(MPI_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} AND
- "${MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" EQUAL "0")
+ MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} EQUAL "0")
string(STRIP "${MPI_RUN_OUTPUT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}"
MPI_${LANG}_LIBRARY_VERSION_STRING)
else()
@@ -1778,12 +1780,12 @@ foreach(LANG IN ITEMS C CXX Fortran)
set(MPI_${LANG}_FIND_VERSION_EXACT ${MPI_FIND_VERSION_EXACT})
unset(MPI_${LANG}_REQUIRED_VARS)
- if (NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}")
+ if (NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER)
foreach(mpilibname IN LISTS MPI_${LANG}_LIB_NAMES)
list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpilibname}_LIBRARY")
endforeach()
list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_LIB_NAMES")
- if("${LANG}" STREQUAL "Fortran")
+ if(LANG STREQUAL "Fortran")
# For Fortran we only need one of the module or header directories to have *some* support for MPI.
if(NOT MPI_${LANG}_MODULE_DIR)
list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_F77_HEADER_DIR")
@@ -1883,7 +1885,7 @@ else()
endif()
list(LENGTH MPI_LIBRARIES MPI_NUMLIBS)
-if (MPI_NUMLIBS GREATER 1)
+if (MPI_NUMLIBS GREATER "1")
set(MPI_EXTRA_LIBRARY_WORK "${MPI_LIBRARIES}")
list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0)
set(MPI_EXTRA_LIBRARY "${MPI_EXTRA_LIBRARY_WORK}")
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 470ebe0ea..07a9adf2e 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -85,10 +85,18 @@ Module Input Variables
Users or projects may set the following variables to configure the module
behavior:
+:variable:`Matlab_ROOT <<PackageName>_ROOT>`
+ .. versionadded:: 3.25
+
+ Default value for :variable:`Matlab_ROOT_DIR`, the root of the Matlab
+ installation.
+
:variable:`Matlab_ROOT_DIR`
- the root of the Matlab installation.
+ The root of the Matlab installation.
+
:variable:`MATLAB_FIND_DEBUG`
outputs debug information
+
:variable:`MATLAB_ADDITIONAL_VERSIONS`
additional versions of Matlab for the automatic retrieval of the installed
versions.
@@ -844,6 +852,15 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve
endif()
endif()
+ if(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp")
+ # last resort check as some HPC with "module load matlab" not enacted fail to catch in earlier checks
+ # and error CMake configure even if find_package(Matlab) is not REQUIRED
+ if(MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Unable to determine the version of Matlab. The version log file does not exist.")
+ endif()
+ return()
+ endif()
+
# if successful, read back the log
file(READ "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp" _matlab_version_from_cmd)
file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp")
@@ -1573,6 +1590,13 @@ endfunction()
# this variable will get all Matlab installations found in the current system.
set(_matlab_possible_roots)
+if(NOT DEFINED Matlab_ROOT AND DEFINED ENV{Matlab_ROOT})
+ set(Matlab_ROOT $ENV{Matlab_ROOT})
+endif()
+if(DEFINED Matlab_ROOT)
+ set(Matlab_ROOT_DIR ${Matlab_ROOT})
+endif()
+
if(Matlab_ROOT_DIR)
# if the user specifies a possible root, we keep this one
diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake
index cf58f3b80..00e42b8ea 100644
--- a/Modules/FindOpenACC.cmake
+++ b/Modules/FindOpenACC.cmake
@@ -27,6 +27,13 @@ The module provides :prop_tgt:`IMPORTED` targets:
Variables
^^^^^^^^^
+The module defines the following variables:
+
+``OpenACC_FOUND``
+ .. versionadded:: 3.25
+
+ Variable indicating that OpenACC flags for at least one languages have been found.
+
This module will set the following variables per language in your
project, where ``<lang>`` is one of C, CXX, or Fortran:
@@ -121,21 +128,18 @@ set(OpenACC_Fortran_CHECK_VERSION_SOURCE
)
-function(_OPENACC_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
- set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC)
+macro(_OPENACC_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR)
if("${LANG}" STREQUAL "C")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
- file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.c")
+ set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
elseif("${LANG}" STREQUAL "CXX")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
- file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp")
+ set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
elseif("${LANG}" STREQUAL "Fortran")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.F90")
- file(WRITE "${SRC_FILE}_in" "${OpenACC_Fortran_${SRC_FILE_CONTENT_VAR}}")
- configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.F90")
+ set(${CONTENT_VAR} "${OpenACC_Fortran_${CONTENT_ID}}")
endif()
- set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
-endfunction()
+endmacro()
function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR)
@@ -177,10 +181,12 @@ endfunction()
function(_OPENACC_GET_FLAGS LANG FLAG_VAR)
set(FLAG_CANDIDATES "")
_OPENACC_GET_FLAGS_CANDIDATE("${LANG}" FLAG_CANDIDATES)
- _OPENACC_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenACCTryFlag _OPENACC_TEST_SRC)
+ _OPENACC_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenACCTryFlag
+ _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
foreach(FLAG IN LISTS FLAG_CANDIDATES)
- try_compile(OpenACC_FLAG_TEST_RESULT ${CMAKE_BINARY_DIR} ${_OPENACC_TEST_SRC}
+ try_compile(OpenACC_FLAG_TEST_RESULT
+ SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${FLAG}"
OUTPUT_VARIABLE OpenACC_TRY_COMPILE_OUTPUT
)
@@ -205,13 +211,15 @@ endfunction()
function(_OPENACC_GET_SPEC_DATE LANG SPEC_DATE)
- _OPENACC_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenACCCheckVersion _OPENACC_TEST_SRC)
+ _OPENACC_PREPARE_SOURCE(${LANG} CHECK_VERSION_SOURCE OpenACCCheckVersion
+ _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC/accver_${LANG}.bin")
- try_compile(OpenACC_SPECTEST_${LANG} "${CMAKE_BINARY_DIR}" "${_OPENACC_TEST_SRC}"
- CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}"
- COPY_FILE ${BIN_FILE}
- OUTPUT_VARIABLE OUTPUT)
+ try_compile(OpenACC_SPECTEST_${LANG}
+ SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}"
+ COPY_FILE "${BIN_FILE}"
+ OUTPUT_VARIABLE OUTPUT)
if(${OpenACC_SPECTEST_${LANG}})
file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenACC-date")
@@ -270,6 +278,9 @@ foreach (LANG IN ITEMS C CXX Fortran)
REQUIRED_VARS OpenACC_${LANG}_FLAGS
VERSION_VAR OpenACC_${LANG}_VERSION
)
+ if(OpenACC_${LANG}_FOUND)
+ set(OpenACC_FOUND TRUE)
+ endif()
endif()
endforeach()
diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake
index b5b92c568..53aafdc0c 100644
--- a/Modules/FindOpenAL.cmake
+++ b/Modules/FindOpenAL.cmake
@@ -29,6 +29,16 @@ OpenAL is searched in the following order:
5. Manually compiled framework: ``/Library/Frameworks``.
6. Add-on package: ``/opt``.
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.25
+
+This module defines the :prop_tgt:`IMPORTED` target:
+
+``OpenAL::OpenAL``
+ The OpenAL library, if found.
+
Result Variables
^^^^^^^^^^^^^^^^
@@ -94,3 +104,19 @@ find_package_handle_standard_args(
)
mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
+
+if(OPENAL_INCLUDE_DIR AND OPENAL_LIBRARY)
+ if(NOT TARGET OpenAL::OpenAL)
+ if(EXISTS "${OPENAL_LIBRARY}")
+ add_library(OpenAL::OpenAL UNKNOWN IMPORTED)
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ IMPORTED_LOCATION "${OPENAL_LIBRARY}")
+ else()
+ add_library(OpenAL::OpenAL INTERFACE IMPORTED)
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ IMPORTED_LIBNAME "${OPENAL_LIBRARY}")
+ endif()
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${OPENAL_INCLUDE_DIR}")
+ endif()
+endif()
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index d6d1c0000..a9a1b2aec 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -377,7 +377,7 @@ else()
(NOT OPENGL_USE_EGL AND
NOT OPENGL_glx_LIBRARY AND
OPENGL_gl_LIBRARY))
- list(APPEND _OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY)
+ list(PREPEND _OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY)
endif()
# We always need the 'gl.h' include dir.
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index ecfb7f9ba..9e2492579 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -178,27 +178,25 @@ set(OpenMP_Fortran_TEST_SOURCE
"
)
-function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
- set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
+macro(_OPENMP_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR)
if("${LANG}" STREQUAL "C")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
- file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.c")
+ set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}")
elseif("${LANG}" STREQUAL "CXX")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
- file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp")
+ set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}")
elseif("${LANG}" STREQUAL "Fortran")
- set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
- file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
- configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
+ set(${FULLNAME_VAR} "${NAME_PREFIX}.F90")
+ string(CONFIGURE "${OpenMP_Fortran_${CONTENT_ID}}" ${CONTENT_VAR} @ONLY)
endif()
- set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
-endfunction()
+endmacro()
include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake)
function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
_OPENMP_FLAG_CANDIDATES("${LANG}")
- _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
+ _OPENMP_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenMPTryFlag
+ _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT)
unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
@@ -214,7 +212,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
endif()
string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
- try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
+ SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
@@ -238,11 +237,29 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
OpenMP_${LANG}_IMPLICIT_FWK_DIRS
OpenMP_${LANG}_LOG_VAR
"${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
+ LANGUAGE ${LANG}
)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
+ # For LCC we should additionally alanyze -print-search-dirs output
+ # to check for additional implicit_dirs.
+ # Note: This won't work if CMP0129 policy is set to OLD!
+ if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "LCC")
+ execute_process(
+ COMMAND ${CMAKE_${LANG}_COMPILER} -print-search-dirs
+ OUTPUT_VARIABLE output_lines
+ COMMAND_ERROR_IS_FATAL ANY
+ ERROR_QUIET)
+ if("${output_lines}" MATCHES ".*\nlibraries:[ \t]+(.*:)\n.*")
+ string(REPLACE ":" ";" implicit_dirs_addon "${CMAKE_MATCH_1}")
+ list(PREPEND OpenMP_${LANG}_IMPLICIT_LINK_DIRS ${implicit_dirs_addon})
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ " Extended OpenMP library search paths: [${implicit_dirs}]\n")
+ endif()
+ endif()
+
unset(_OPENMP_LIB_NAMES)
foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
@@ -262,7 +279,9 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
CMAKE_FIND_ROOT_PATH_BOTH
- NO_DEFAULT_PATH
+ NO_PACKAGE_ROOT_PATH
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
)
endif()
mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
@@ -291,7 +310,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
# Try without specifying include directory first. We only want to
# explicitly add a search path if the header can't be found on the
# default header search path already.
- try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
+ SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
@@ -301,7 +321,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR)
set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE)
if(OpenMP_${LANG}_INCLUDE_DIR)
- try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
+ SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
"-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
@@ -323,7 +344,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
)
mark_as_advanced(OpenMP_libomp_LIBRARY)
if(OpenMP_libomp_LIBRARY)
- try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
+ SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
@@ -385,7 +407,8 @@ set(OpenMP_Fortran_CHECK_VERSION_SOURCE
")
function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
- _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
+ _OPENMP_PREPARE_SOURCE("${LANG}" CHECK_VERSION_SOURCE OpenMPCheckVersion
+ _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT)
unset(_includeDirFlags)
if(OpenMP_${LANG}_INCLUDE_DIR)
@@ -394,10 +417,11 @@ function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
- try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
- CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags}
- COPY_FILE ${BIN_FILE}
- OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
+ try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}
+ SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags}
+ COPY_FILE "${BIN_FILE}"
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
@@ -460,10 +484,14 @@ foreach(LANG IN ITEMS C CXX)
if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
_OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
- set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
- CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
- set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
- CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
+ if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
+ CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
+ CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
+ endif()
mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
endif()
endif()
@@ -479,10 +507,14 @@ if(CMAKE_Fortran_COMPILER_LOADED)
set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
endif()
- set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
- CACHE STRING "Fortran compiler flags for OpenMP parallelization")
- set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
- CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
+ endif()
mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
endif()
@@ -495,11 +527,14 @@ if(CMAKE_Fortran_COMPILER_LOADED)
set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
endif()
- set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
- CACHE STRING "Fortran compiler flags for OpenMP parallelization")
-
- set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
- CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
+ endif()
endif()
if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
@@ -571,7 +606,8 @@ foreach(LANG IN LISTS OpenMP_FINDLIST)
separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
- if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu")
+ if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu"
+ OR ${CMAKE_${LANG}_COMPILER_ID} STREQUAL "IntelLLVM")
set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}")
endif()
diff --git a/Modules/FindOpenSP.cmake b/Modules/FindOpenSP.cmake
new file mode 100644
index 000000000..655dd6572
--- /dev/null
+++ b/Modules/FindOpenSP.cmake
@@ -0,0 +1,155 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindOpenSP
+----------
+
+.. versionadded:: 3.25
+
+Try to find the OpenSP library.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables:
+
+``OpenSP_FOUND``
+ True if (the requested version of) ``OpenSP`` is available
+
+``OpenSP_VERSION``
+ The version of ``OpenSP``
+
+``OpenSP_VERSION_MAJOR``
+ The major version of ``OpenSP``
+
+``OpenSP_VERSION_MINOR``
+ The minor version of ``OpenSP``
+
+``OpenSP_VERSION_PATCH``
+ The patch version of ``OpenSP``
+
+``OpenSP_INCLUDE_DIRS``
+ The include dirs of ``OpenSP`` with its headers
+
+``OpenSP_LIBRARIES``
+ The OpenSP library for use with target_link_libraries().
+ This can be passed to target_link_libraries() instead of
+ the :prop_tgt:`IMPORTED` ``OpenSP::OpenSP`` target
+
+``OpenSP_MULTI_BYTE``
+ True if ``SP_MULTI_BYTE`` was found to be defined in OpenSP's ``config.h``
+ header file, which indicates that the ``OpenSP`` library was compiled with
+ support for multi-byte characters. The consuming target needs to define the
+ ``SP_MULTI_BYTE`` to match this value in order to avoid issues with character
+ decoding.
+
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the :prop_tgt:`IMPORTED` target ``OpenSP::OpenSP``, if
+OpenSP has been found.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``OpenSP_INCLUDE_DIR``
+ the OpenSP include directory
+
+``OpenSP_LIBRARY``
+ the absolute path of the osp library
+
+#]=======================================================================]
+
+if (NOT OpenSP_INCLUDE_DIR AND NOT OpenSP_LIBRARY)
+ find_package(PkgConfig)
+ if (PkgConfig_FOUND)
+ pkg_check_modules(OpenSP IMPORTED_TARGET GLOBAL opensp)
+
+ if (OpenSP_FOUND)
+ add_library(OpenSP::OpenSP INTERFACE IMPORTED)
+ target_link_libraries(OpenSP::OpenSP INTERFACE PkgConfig::OpenSP)
+
+ set(OpenSP_INCLUDE_DIR ${OpenSP_INCLUDE_DIRS})
+ set(OpenSP_LIBRARY ${OpenSP_LIBRARIES})
+ endif ()
+ endif ()
+endif ()
+
+if (NOT OpenSP_INCLUDE_DIR)
+ find_path(OpenSP_INCLUDE_DIR
+ NAMES ParserEventGeneratorKit.h
+ PATH_SUFFIXES OpenSP opensp
+ DOC "The OpenSP include directory"
+ )
+endif ()
+
+if (NOT OpenSP_LIBRARY)
+ find_library(OpenSP_LIBRARY_RELEASE
+ NAMES osp libosp opensp libopensp sp133 libsp
+ )
+
+ find_library(OpenSP_LIBRARY_DEBUG
+ NAMES ospd libospd openspd libopenspd sp133d libspd
+ )
+
+ include(SelectLibraryConfigurations)
+ select_library_configurations(OpenSP)
+endif ()
+
+if (OpenSP_INCLUDE_DIR AND OpenSP_LIBRARY)
+ if (EXISTS "${OpenSP_INCLUDE_DIR}/config.h")
+ if (NOT OpenSP_VERSION)
+ file(STRINGS "${OpenSP_INCLUDE_DIR}/config.h" opensp_version_str REGEX "^#define[\t ]+SP_VERSION[\t ]+\".*\"")
+ string(REGEX REPLACE "^.*SP_VERSION[\t ]+\"([^\"]*)\".*$" "\\1" OpenSP_VERSION "${opensp_version_str}")
+ unset(opensp_version_str)
+ endif ()
+
+ if (OpenSP_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=])
+ set(OpenSP_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(OpenSP_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(OpenSP_VERSION_PATCH "${CMAKE_MATCH_3}")
+ endif ()
+
+ include(CheckCXXSymbolExists)
+ check_cxx_symbol_exists(SP_MULTI_BYTE "${OpenSP_INCLUDE_DIR}/config.h" OpenSP_MULTI_BYTE)
+ endif ()
+
+ if (NOT TARGET OpenSP::OpenSP)
+ set(OpenSP_INCLUDE_DIRS ${OpenSP_INCLUDE_DIR})
+
+ add_library(OpenSP::OpenSP UNKNOWN IMPORTED)
+ set_target_properties(OpenSP::OpenSP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenSP_INCLUDE_DIRS}")
+
+ if (OpenSP_LIBRARY_RELEASE)
+ set_target_properties(OpenSP::OpenSP PROPERTIES IMPORTED_LOCATION_RELEASE "${OpenSP_LIBRARY_RELEASE}")
+ set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+ endif ()
+
+ if (OpenSP_LIBRARY_DEBUG)
+ set_target_properties(OpenSP::OpenSP PROPERTIES IMPORTED_LOCATION_DEBUG "${OpenSP_LIBRARY_DEBUG}")
+ set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+ endif ()
+
+ if (NOT OpenSP_LIBRARY_RELEASE AND NOT OpenSP_LIBRARY_DEBUG)
+ set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_LOCATION "${OpenSP_LIBRARY}")
+ endif ()
+ endif ()
+endif ()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(OpenSP
+ FOUND_VAR OpenSP_FOUND
+ REQUIRED_VARS OpenSP_LIBRARY OpenSP_INCLUDE_DIR
+ VERSION_VAR OpenSP_VERSION
+ )
+
+mark_as_advanced(OpenSP_INCLUDE_DIR OpenSP_LIBRARY OpenSP_MULTI_BYTE)
+
+include(FeatureSummary)
+set_package_properties(OpenSP PROPERTIES
+ URL "http://openjade.sourceforge.net/doc/index.htm"
+ DESCRIPTION "An SGML System Conforming to International Standard ISO 8879"
+ )
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 927856672..f66ffcf61 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -90,13 +90,25 @@ This module will set the following variables in your project:
Hints
^^^^^
-Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
+The following variables may be set to control search behavior:
-.. versionadded:: 3.4
- Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
+``OPENSSL_ROOT_DIR``
+ Set to the root directory of an OpenSSL installation.
+
+``OPENSSL_USE_STATIC_LIBS``
+ .. versionadded:: 3.4
+
+ Set to ``TRUE`` to look for static libraries.
+
+``OPENSSL_MSVC_STATIC_RT``
+ .. versionadded:: 3.5
+
+ Set to ``TRUE`` to choose the MT version of the lib.
-.. versionadded:: 3.5
- Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
+``ENV{PKG_CONFIG_PATH}``
+ On UNIX-like systems, ``pkg-config`` is used to locate the system OpenSSL.
+ Set the ``PKG_CONFIG_PATH`` environment varialbe to look in alternate
+ locations. Useful on multi-lib systems.
#]=======================================================================]
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
@@ -392,6 +404,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
+ "lib64"
)
find_library(SSL_EAY
@@ -402,6 +415,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
+ "lib64"
)
mark_as_advanced(SSL_EAY LIB_EAY)
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index fbcf7cd88..56ba1e672 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -535,18 +535,24 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
set(VERSION_MSG "")
set(VERSION_OK TRUE)
- # check with DEFINED here as the requested or found version may be "0"
+ # check that the version variable is not empty to avoid emitting a misleading
+ # message (i.e. `Found unsuitable version ""`)
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
- set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
- if (FPHSA_HANDLE_VERSION_RANGE)
- set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE)
+ if(NOT "${${FPHSA_VERSION_VAR}}" STREQUAL "")
+ set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
+ if (FPHSA_HANDLE_VERSION_RANGE)
+ set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE)
+ else()
+ set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE)
+ endif()
+ find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG
+ ${FPCV_HANDLE_VERSION_RANGE})
else()
- set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE)
+ set(VERSION_OK FALSE)
endif()
- find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG
- ${FPCV_HANDLE_VERSION_RANGE})
- else()
+ endif()
+ if("${${FPHSA_VERSION_VAR}}" STREQUAL "")
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake
index 375cb7027..04f9d8c28 100644
--- a/Modules/FindPython.cmake
+++ b/Modules/FindPython.cmake
@@ -237,8 +237,8 @@ Hints
``Python_FIND_ABI``
.. versionadded:: 3.16
- This variable defines which ABIs, as defined in
- `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
+ This variable defines which ABIs, as defined in :pep:`3149`, should be
+ searched.
.. note::
@@ -363,7 +363,7 @@ Hints
``Anaconda`` or ``ActivePython``, rely on this implementation.
* ``IronPython``: This implementation use the ``CSharp`` language for
``.NET Framework`` on top of the `Dynamic Language Runtime` (``DLR``).
- See `IronPython <http://ironpython.net>`_.
+ See `IronPython <https://ironpython.net>`_.
* ``PyPy``: This implementation use ``RPython`` language and
``RPython translation toolchain`` to produce the python interpreter.
See `PyPy <https://www.pypy.org>`_.
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index c4fae6b01..7a127e4b4 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -14,6 +14,8 @@ cmake_policy(PUSH)
cmake_policy (SET CMP0012 NEW)
# IN_LIST operator
cmake_policy (SET CMP0057 NEW)
+# registry view behavior
+cmake_policy (SET CMP0134 NEW)
if (NOT DEFINED _PYTHON_PREFIX)
message (FATAL_ERROR "FindPython: INTERNAL ERROR")
@@ -175,30 +177,31 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS)
foreach (version IN LISTS _PGR_VERSION)
string (REPLACE "." "" version_no_dots ${version})
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
if (version VERSION_GREATER_EQUAL "3.5")
+ # cmake_host_system_information is not usable in bootstrap
get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME)
if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit")
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
endif()
else()
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
endif()
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
endforeach()
elseif (implementation STREQUAL "IronPython")
foreach (version IN LISTS _PGR_VERSION)
- list (APPEND registries [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${version}\\InstallPath])
+ list (APPEND registries [HKEY_LOCAL_MACHINE/SOFTWARE/IronPython/${version}/InstallPath])
endforeach()
endif()
endforeach()
@@ -711,7 +714,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}")
# interpreter does not exist anymore
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -732,7 +735,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
endif()
if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -748,7 +751,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (result)
# interpreter is not usable
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -773,7 +776,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (_PVI_EXACT AND NOT version VERSION_EQUAL _PVI_VERSION)
# interpreter has wrong version
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
else()
@@ -782,7 +785,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVI_VERSION}")
if (NOT major_version VERSION_EQUAL expected_major_version
OR NOT version VERSION_GREATER_EQUAL _PVI_VERSION)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -794,7 +797,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# interpreter has invalid version
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -813,9 +816,9 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# interpreter not usable or has wrong major version
if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
@@ -836,9 +839,9 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
# interpreter not usable or has wrong architecture
if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
@@ -846,6 +849,14 @@ function (_PYTHON_VALIDATE_INTERPRETER)
endif()
endfunction()
+function(_python_validate_find_interpreter status interpreter)
+ set(_${_PYTHON_PREFIX}_EXECUTABLE "${interpreter}" CACHE FILEPATH "" FORCE)
+ _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
+ set (${status} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
function (_PYTHON_VALIDATE_COMPILER)
if (NOT _${_PYTHON_PREFIX}_COMPILER)
@@ -856,7 +867,7 @@ function (_PYTHON_VALIDATE_COMPILER)
if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}")
# Compiler does not exist anymore
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -883,7 +894,7 @@ function (_PYTHON_VALIDATE_COMPILER)
file (REMOVE_RECURSE "${working_dir}")
if (result)
# compiler is not usable
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -909,7 +920,7 @@ function (_PYTHON_VALIDATE_COMPILER)
if (_PVC_EXACT AND NOT version VERSION_EQUAL _PVC_VERSION)
# interpreter has wrong version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
else()
@@ -918,7 +929,7 @@ function (_PYTHON_VALIDATE_COMPILER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVC_VERSION}")
if (NOT major_version VERSION_EQUAL expected_major_version
OR NOT version VERSION_GREATER_EQUAL _PVC_VERSION)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -930,7 +941,7 @@ function (_PYTHON_VALIDATE_COMPILER)
find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# interpreter has invalid version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -939,13 +950,21 @@ function (_PYTHON_VALIDATE_COMPILER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" major_version "${version}")
if (NOT major_version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# Compiler has wrong major version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
endif()
endfunction()
+function(_python_validate_find_compiler status compiler)
+ set(_${_PYTHON_PREFIX}_COMPILER "${compiler}" CACHE FILEPATH "" FORCE)
+ _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ if (NOT _${_PYTHON_PREFIX}_COMPILER)
+ set (${status} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
function (_PYTHON_VALIDATE_LIBRARY)
if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
@@ -957,7 +976,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
# library does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
if (WIN32)
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
@@ -971,7 +990,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
else()
if (_PVL_VERSION OR _PVL_IN_RANGE)
@@ -980,7 +999,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
string (REGEX MATCH "[0-9](\\.[0-9]+)?" version "${_PVL_VERSION}")
if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL version) OR (lib_VERSION VERSION_LESS version))
# library has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
@@ -990,14 +1009,14 @@ function (_PYTHON_VALIDATE_LIBRARY)
find_package_check_version ("${lib_VERSION}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# library has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
else()
if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# library has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
@@ -1023,7 +1042,7 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
# include file does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
return()
endif()
@@ -1033,14 +1052,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
else()
if (_PVID_VERSION OR _PVID_IN_RANGE)
if (_PVID_VERSION)
if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version))
# include dir has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
@@ -1050,14 +1069,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
find_package_check_version ("${inc_VERSION}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# include dir has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
else()
if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# include dir has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
@@ -1247,12 +1266,14 @@ if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY)
endif()
# Python and Anaconda distributions: define which architectures can be used
+unset (_${_PYTHON_PREFIX}_REGISTRY_VIEW)
if (CMAKE_SIZEOF_VOID_P)
math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
# In this case, search only for 64bit or 32bit
set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
+ set (_${_PYTHON_PREFIX}_REGISTRY_VIEW REGISTRY_VIEW ${_${_PYTHON_PREFIX}_ARCH})
else()
if (_${_PYTHON_PREFIX}_ARCH EQUAL "32")
set (_${_PYTHON_PREFIX}_ARCH2 64)
@@ -1506,9 +1527,13 @@ endfunction()
unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
unset (_${_PYTHON_PREFIX}_CACHED_VARS)
unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE INTERNAL "Interpreter reason failure")
unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE INTERNAL "Compiler reason failure")
unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE INTERNAL "Development reason failure")
unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE INTERNAL "NumPy reason failure")
# preamble
@@ -1590,9 +1615,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
-
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1612,8 +1636,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1626,9 +1650,10 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1641,8 +1666,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1650,8 +1675,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
NAMES ${_${_PYTHON_PREFIX}_NAMES}
NAMES_PER_DIR
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1663,8 +1688,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1676,8 +1701,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1687,9 +1713,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endwhile()
else()
# look-up for various versions and locations
- set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT)
+ set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT)
if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE)
- list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE)
+ list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE)
endif()
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
@@ -1698,6 +1724,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
_python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION})
_python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS})
# Virtual environments handling
if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
@@ -1710,8 +1737,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1731,7 +1758,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
# Windows registry
@@ -1742,11 +1770,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1758,21 +1787,18 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
+
# try using standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
NAMES ${_${_PYTHON_PREFIX}_NAMES}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NAMES_PER_DIR
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1784,7 +1810,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
# Windows registry
@@ -1794,10 +1821,11 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1806,15 +1834,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND
NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
# No specific version found. Retry with generic names and standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
_python_get_names (_${_PYTHON_PREFIX}_NAMES POSIX INTERPRETER)
+ unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS)
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES})
- _python_validate_interpreter ()
+ NAMES ${_${_PYTHON_PREFIX}_NAMES}
+ NAMES_PER_DIR
+ VALIDATOR _python_validate_find_interpreter)
endif()
endif()
endif()
@@ -1836,7 +1861,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
# Interpreter is not usable
set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE)
unset (${_PYTHON_PREFIX}_VERSION)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
endif()
@@ -1884,7 +1909,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endif()
if (${_PYTHON_PREFIX}_Interpreter_FOUND)
- unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE)
# compute and save interpreter signature
string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}")
@@ -2058,8 +2083,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2072,9 +2097,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2087,8 +2113,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2097,8 +2123,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
find_program (_${_PYTHON_PREFIX}_COMPILER
NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES}
NAMES_PER_DIR
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2110,12 +2136,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
endif()
+
# Windows registry
if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
find_program (_${_PYTHON_PREFIX}_COMPILER
@@ -2123,8 +2150,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2134,9 +2162,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endwhile()
else()
# try using root dir and registry
- set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT)
+ set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT)
if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE)
- list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE)
+ list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE)
endif()
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
@@ -2157,6 +2185,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
IMPLEMENTATIONS IronPython
VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS})
+
# Apple frameworks handling
if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
find_program (_${_PYTHON_PREFIX}_COMPILER
@@ -2168,8 +2198,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2182,9 +2212,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2197,8 +2228,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2210,8 +2241,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2223,8 +2254,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2240,11 +2272,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
IMPLEMENTATIONS IronPython
VERSION ${_${_PYTHON_PREFIX}_FIND_VERSIONS}
COMPILER)
+ unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS)
find_program (_${_PYTHON_PREFIX}_COMPILER
NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES}
+ NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_compiler ()
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_compiler)
endif()
endif()
@@ -2285,7 +2319,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
else()
# compiler not usable
set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
endif()
file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
endif()
@@ -2304,7 +2338,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endif()
if (${_PYTHON_PREFIX}_Compiler_FOUND)
- unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE)
# compute and save compiler signature
string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}")
@@ -2786,7 +2820,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
@@ -2837,7 +2871,15 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
while (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED TRUE)
+ foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Module Embed)
+ string (TOUPPER "${_${_PYTHON_PREFIX}_COMPONENT}" _${_PYTHON_PREFIX}_ID)
+ if ("Development.${_${_PYTHON_PREFIX}_COMPONENT}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND NOT "LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${_${_PYTHON_PREFIX}_ID}_ARTIFACTS)
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED FALSE)
+ endif()
+ endforeach()
+ if (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED
AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
# Don't search for include dir if no library was founded
break()
@@ -2939,7 +2981,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
@@ -3033,7 +3075,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
AND ${_PYTHON_PREFIX}_Development.Embed_FOUND)
OR (NOT "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
AND ${_PYTHON_PREFIX}_Development.Module_FOUND))
- unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE)
endif()
if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
@@ -3144,7 +3186,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte
set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_NumPy_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND")
endif()
@@ -3166,7 +3208,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte
endif()
if (${_PYTHON_PREFIX}_NumPy_FOUND)
- unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE)
# compute and save numpy signature
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}")
@@ -3196,7 +3238,7 @@ unset (_${_PYTHON_PREFIX}_REASON_FAILURE)
foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy)
if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE)
string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}")
- unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE CACHE)
endif()
endforeach()
diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake
index 0888fad7e..268acfef1 100644
--- a/Modules/FindPython2.cmake
+++ b/Modules/FindPython2.cmake
@@ -302,7 +302,7 @@ Hints
``Anaconda`` or ``ActivePython``, rely on this implementation.
* ``IronPython``: This implementation use the ``CSharp`` language for
``.NET Framework`` on top of the `Dynamic Language Runtime` (``DLR``).
- See `IronPython <http://ironpython.net>`_.
+ See `IronPython <https://ironpython.net>`_.
* ``PyPy``: This implementation use ``RPython`` language and
``RPython translation toolchain`` to produce the python interpreter.
See `PyPy <https://www.pypy.org>`_.
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake
index 145c95e11..4f198bb5e 100644
--- a/Modules/FindPython3.cmake
+++ b/Modules/FindPython3.cmake
@@ -239,8 +239,8 @@ Hints
``Python3_FIND_ABI``
.. versionadded:: 3.16
- This variable defines which ABIs, as defined in
- `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
+ This variable defines which ABIs, as defined in :pep:`3149`, should be
+ searched.
.. note::
@@ -361,7 +361,7 @@ Hints
``Anaconda`` or ``ActivePython``, rely on this implementation.
* ``IronPython``: This implementation use the ``CSharp`` language for
``.NET Framework`` on top of the `Dynamic Language Runtime` (``DLR``).
- See `IronPython <http://ironpython.net>`_.
+ See `IronPython <https://ironpython.net>`_.
* ``PyPy``: This implementation use ``RPython`` language and
``RPython translation toolchain`` to produce the python interpreter.
See `PyPy <https://www.pypy.org>`_.
diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake
index a80758d5e..b14349ffc 100644
--- a/Modules/FindRuby.cmake
+++ b/Modules/FindRuby.cmake
@@ -369,56 +369,17 @@ if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
set(Ruby_VERSION_MAJOR 1)
set(Ruby_VERSION_MINOR 9)
endif()
- # check whether we found 2.0.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0")
+ # check whether we found 2.[0-7].x
+ if(${Ruby_EXECUTABLE} MATCHES "ruby2")
set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 0)
+ string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby2\\.?([0-7])" "\\1" Ruby_VERSION_MINOR)
endif()
- # check whether we found 2.1.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 1)
- endif()
- # check whether we found 2.2.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 2)
- endif()
- # check whether we found 2.3.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 3)
- endif()
- # check whether we found 2.4.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 4)
- endif()
- # check whether we found 2.5.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?5")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 5)
- endif()
- # check whether we found 2.6.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?6")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 6)
- endif()
- # check whether we found 2.7.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?7")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 7)
- endif()
- # check whether we found 3.0.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?0")
- set(Ruby_VERSION_MAJOR 3)
- set(Ruby_VERSION_MINOR 0)
- endif()
- # check whether we found 3.1.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?1")
+ # check whether we found 3.[0-1].x
+ if(${Ruby_EXECUTABLE} MATCHES "ruby3")
set(Ruby_VERSION_MAJOR 3)
- set(Ruby_VERSION_MINOR 1)
+ string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby3\\.?([0-1])" "\\1" Ruby_VERSION_MINOR)
endif()
+
endif()
if(Ruby_VERSION_MAJOR)
diff --git a/Modules/FindSDL_gfx.cmake b/Modules/FindSDL_gfx.cmake
new file mode 100644
index 000000000..2dd96e98f
--- /dev/null
+++ b/Modules/FindSDL_gfx.cmake
@@ -0,0 +1,86 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindSDL_gfx
+-----------
+
+.. versionadded:: 3.25
+
+Locate SDL_gfx library
+
+This module defines:
+
+::
+
+ SDL::SDL_gfx, the name of the target to use with target_*() commands
+ SDL_GFX_LIBRARIES, the name of the library to link against
+ SDL_GFX_INCLUDE_DIRS, where to find the headers
+ SDL_GFX_FOUND, if false, do not try to link against
+ SDL_GFX_VERSION_STRING - human-readable string containing the
+ version of SDL_gfx
+
+``$SDLDIR`` is an environment variable that would correspond to the
+``./configure --prefix=$SDLDIR`` used in building SDL.
+#]=======================================================================]
+
+find_path(SDL_GFX_INCLUDE_DIRS
+ NAMES
+ SDL_framerate.h
+ SDL_gfxBlitFunc.h
+ SDL_gfxPrimitives.h
+ SDL_gfxPrimitives_font.h
+ SDL_imageFilter.h
+ SDL_rotozoom.h
+ HINTS
+ ENV SDLGFXDIR
+ ENV SDLDIR
+ PATH_SUFFIXES SDL
+ # path suffixes to search inside ENV{SDLDIR}
+ include/SDL include/SDL12 include/SDL11 include
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+ set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL_GFX_LIBRARIES
+ NAMES SDL_gfx
+ HINTS
+ ENV SDLGFXDIR
+ ENV SDLDIR
+ PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
+)
+
+if(SDL_GFX_INCLUDE_DIRS AND EXISTS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h")
+ file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MAJOR[ \t]+[0-9]+$")
+ file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MINOR[ \t]+[0-9]+$")
+ file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MICRO[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MAJOR[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_MAJOR "${SDL_GFX_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MINOR[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_MINOR "${SDL_GFX_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MICRO[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_PATCH "${SDL_GFX_VERSION_PATCH_LINE}")
+ set(SDL_GFX_VERSION_STRING ${SDL_GFX_VERSION_MAJOR}.${SDL_GFX_VERSION_MINOR}.${SDL_GFX_VERSION_PATCH})
+ unset(SDL_GFX_VERSION_MAJOR_LINE)
+ unset(SDL_GFX_VERSION_MINOR_LINE)
+ unset(SDL_GFX_VERSION_PATCH_LINE)
+ unset(SDL_GFX_VERSION_MAJOR)
+ unset(SDL_GFX_VERSION_MINOR)
+ unset(SDL_GFX_VERSION_PATCH)
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_gfx
+ REQUIRED_VARS SDL_GFX_LIBRARIES SDL_GFX_INCLUDE_DIRS
+ VERSION_VAR SDL_GFX_VERSION_STRING)
+
+if(SDL_gfx_FOUND)
+ if(NOT TARGET SDL::SDL_gfx)
+ add_library(SDL::SDL_gfx INTERFACE IMPORTED)
+ set_target_properties(SDL::SDL_gfx PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${SDL_GFX_INCLUDE_DIRS}"
+ INTERFACE_LINK_LIBRARIES "${SDL_GFX_LIBRARIES}")
+ endif()
+endif()
diff --git a/Modules/FindSDL_image.cmake b/Modules/FindSDL_image.cmake
index e687b4983..324fef5d2 100644
--- a/Modules/FindSDL_image.cmake
+++ b/Modules/FindSDL_image.cmake
@@ -31,10 +31,6 @@ For backward compatibility the following variables are also set:
$SDLDIR is an environment variable that would correspond to the
./configure --prefix=$SDLDIR used in building SDL.
-
-Created by Eric Wing. This was influenced by the FindSDL.cmake
-module, but with modifications to recognize OS X frameworks and
-additional Unix paths (FreeBSD, etc).
#]=======================================================================]
if(NOT SDL_IMAGE_INCLUDE_DIR AND SDLIMAGE_INCLUDE_DIR)
diff --git a/Modules/FindSDL_mixer.cmake b/Modules/FindSDL_mixer.cmake
index 315400a30..8ed3cb4ba 100644
--- a/Modules/FindSDL_mixer.cmake
+++ b/Modules/FindSDL_mixer.cmake
@@ -31,10 +31,6 @@ For backward compatibility the following variables are also set:
$SDLDIR is an environment variable that would correspond to the
./configure --prefix=$SDLDIR used in building SDL.
-
-Created by Eric Wing. This was influenced by the FindSDL.cmake
-module, but with modifications to recognize OS X frameworks and
-additional Unix paths (FreeBSD, etc).
#]=======================================================================]
if(NOT SDL_MIXER_INCLUDE_DIR AND SDLMIXER_INCLUDE_DIR)
diff --git a/Modules/FindSDL_net.cmake b/Modules/FindSDL_net.cmake
index 28cb4d6c2..639e5bd78 100644
--- a/Modules/FindSDL_net.cmake
+++ b/Modules/FindSDL_net.cmake
@@ -30,10 +30,6 @@ For backward compatibility the following variables are also set:
$SDLDIR is an environment variable that would correspond to the
./configure --prefix=$SDLDIR used in building SDL.
-
-Created by Eric Wing. This was influenced by the FindSDL.cmake
-module, but with modifications to recognize OS X frameworks and
-additional Unix paths (FreeBSD, etc).
#]=======================================================================]
if(NOT SDL_NET_INCLUDE_DIR AND SDLNET_INCLUDE_DIR)
diff --git a/Modules/FindSDL_sound.cmake b/Modules/FindSDL_sound.cmake
index 8d2f9f8fc..d863e3c1e 100644
--- a/Modules/FindSDL_sound.cmake
+++ b/Modules/FindSDL_sound.cmake
@@ -54,7 +54,19 @@ Typically, you should not use these variables directly, and you should
use SDL_SOUND_LIBRARIES which contains SDL_SOUND_LIBRARY and the other
audio libraries (if needed) to successfully compile on your system.
-Created by Eric Wing. This module is a bit more complicated than the
+Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that
+would correspond to the ./configure --prefix=$SDLDIR used in building
+SDL.
+
+On OSX, this will prefer the Framework version (if found) over others.
+People will have to manually change the cache values of SDL_LIBRARY to
+override this selectionor set the CMake environment CMAKE_INCLUDE_PATH
+to modify the search paths.
+#]=======================================================================]
+
+
+#[[
+This module is a bit more complicated than the
other FindSDL* family modules. The reason is that SDL_sound can be
compiled in a large variety of different ways which are independent of
platform. SDL_sound may dynamically link against other 3rd party
@@ -70,16 +82,7 @@ This module uses a brute force approach to create a test program that
uses SDL_sound, and then tries to build it. If the build fails, it
parses the error output for known symbol names to figure out which
libraries are needed.
-
-Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that
-would correspond to the ./configure --prefix=$SDLDIR used in building
-SDL.
-
-On OSX, this will prefer the Framework version (if found) over others.
-People will have to manually change the cache values of SDL_LIBRARY to
-override this selectionor set the CMake environment CMAKE_INCLUDE_PATH
-to modify the search paths.
-#]=======================================================================]
+#]]
set(SDL_SOUND_EXTRAS "" CACHE STRING "SDL_sound extra flags")
mark_as_advanced(SDL_SOUND_EXTRAS)
@@ -182,9 +185,9 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY)
try_compile(
MY_RESULT
- ${PROJECT_BINARY_DIR}/CMakeTmp
- ${PROJECT_BINARY_DIR}/CMakeTmp
- DetermineSoundLibs
+ PROJECT DetermineSoundLibs
+ SOURCE_DIR ${PROJECT_BINARY_DIR}/CMakeTmp
+ BINARY_DIR ${PROJECT_BINARY_DIR}/CMakeTmp
OUTPUT_VARIABLE MY_OUTPUT
)
diff --git a/Modules/FindSDL_ttf.cmake b/Modules/FindSDL_ttf.cmake
index d5721da0a..d67c08930 100644
--- a/Modules/FindSDL_ttf.cmake
+++ b/Modules/FindSDL_ttf.cmake
@@ -30,10 +30,6 @@ For backward compatibility the following variables are also set:
$SDLDIR is an environment variable that would correspond to the
./configure --prefix=$SDLDIR used in building SDL.
-
-Created by Eric Wing. This was influenced by the FindSDL.cmake
-module, but with modifications to recognize OS X frameworks and
-additional Unix paths (FreeBSD, etc).
#]=======================================================================]
if(NOT SDL_TTF_INCLUDE_DIR AND SDLTTF_INCLUDE_DIR)
diff --git a/Modules/FindSWIG.cmake b/Modules/FindSWIG.cmake
index 7c610d978..370fff05f 100644
--- a/Modules/FindSWIG.cmake
+++ b/Modules/FindSWIG.cmake
@@ -54,7 +54,7 @@ optional Fortran support:
endif()
endif()
-.. _`SWIG`: http://swig.org
+.. _SWIG: https://swig.org
#]=======================================================================]
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index a675fd675..7326ef939 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -129,14 +129,12 @@ macro(_threads_check_flag_pthread)
elseif(NOT DEFINED THREADS_HAVE_PTHREAD_ARG)
message(CHECK_START "Check if compiler accepts -pthread")
if(CMAKE_C_COMPILER_LOADED)
- set(_threads_src ${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c)
+ set(_threads_src CheckForPthreads.c)
elseif(CMAKE_CXX_COMPILER_LOADED)
- set(_threads_src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindThreads/CheckForPthreads.cxx)
- configure_file(${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c "${_threads_src}" COPYONLY)
+ set(_threads_src CheckForPthreads.cxx)
endif()
try_compile(THREADS_HAVE_PTHREAD_ARG
- ${CMAKE_BINARY_DIR}
- ${_threads_src}
+ SOURCE_FROM_FILE "${_threads_src}" "${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c"
CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread
OUTPUT_VARIABLE _cmake_check_pthreads_output)
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index 7ca7d03bf..38179878c 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -36,6 +36,11 @@ There are corresponding imported targets for each of these.
``MoltenVK``
On macOS, an additional component ``MoltenVK`` is available.
+``dxc``
+ .. versionadded:: 3.25
+
+ The DirectX Shader Compiler.
+
The ``glslc`` and ``glslangValidator`` components are provided even
if not explicitly requested (for backward compatibility).
@@ -89,6 +94,21 @@ This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found:
Defined if SDK has the Khronos library which implement a subset of Vulkan API
over Apple Metal graphics framework. (MoltenVK).
+``Vulkan::volk``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the Vulkan meta-loader (volk).
+
+``Vulkan::dxc_lib``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the DirectX shader compiler library.
+
+``Vulkan::dxc_exe``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the DirectX shader compiler CLI tool.
+
Result Variables
^^^^^^^^^^^^^^^^
@@ -128,6 +148,21 @@ This module defines the following variables:
.. versionadded:: 3.24
True, if the SDK has the MoltenVK library.
+``Vulkan_volk_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the volk library.
+
+``Vulkan_dxc_lib_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the DirectX shader compiler library.
+
+``Vulkan_dxc_exe_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the DirectX shader compiler CLI tool.
+
The module will also defines these cache variables:
@@ -156,6 +191,21 @@ The module will also defines these cache variables:
Path to the MoltenVK library.
+``Vulkan_volk_LIBRARY``
+ .. versionadded:: 3.25
+
+ Path to the volk library.
+
+``Vulkan_dxc_LIBRARY``
+ .. versionadded:: 3.25
+
+ Path to the DirectX shader compiler library.
+
+``Vulkan_dxc_EXECUTABLE``
+ .. versionadded:: 3.25
+
+ Path to the DirectX shader compiler CLI tool.
+
Hints
^^^^^
@@ -403,6 +453,27 @@ if(MoltenVK IN_LIST Vulkan_FIND_COMPONENTS)
)
mark_as_advanced(Vulkan_MoltenVK_INCLUDE_DIR)
endif()
+if(volk IN_LIST Vulkan_FIND_COMPONENTS)
+ find_library(Vulkan_volk_LIBRARY
+ NAMES volk
+ HINTS
+ ${_Vulkan_hint_library_search_paths})
+ mark_as_advanced(Vulkan_Volk_LIBRARY)
+endif()
+
+if (dxc IN_LIST Vulkan_FIND_COMPONENTS)
+ find_library(Vulkan_dxc_LIBRARY
+ NAMES dxcompiler
+ HINTS
+ ${_Vulkan_hint_library_search_paths})
+ mark_as_advanced(Vulkan_dxc_LIBRARY)
+
+ find_program(Vulkan_dxc_EXECUTABLE
+ NAMES dxc
+ HINTS
+ ${_Vulkan_hint_executable_search_paths})
+ mark_as_advanced(Vulkan_dxc_EXECUTABLE)
+endif()
if(Vulkan_GLSLC_EXECUTABLE)
set(Vulkan_glslc_FOUND TRUE)
@@ -416,6 +487,12 @@ else()
set(Vulkan_glslangValidator_FOUND FALSE)
endif()
+if (Vulkan_dxc_EXECUTABLE)
+ set(Vulkan_dxc_exe_FOUND TRUE)
+else()
+ set(Vulkan_dxc_exe_FOUND FALSE)
+endif()
+
function(_Vulkan_set_library_component_found component)
cmake_parse_arguments(PARSE_ARGV 1 _ARG
"NO_WARNING"
@@ -466,6 +543,8 @@ _Vulkan_set_library_component_found(glslang
glslang-genericcodegen)
_Vulkan_set_library_component_found(shaderc_combined)
_Vulkan_set_library_component_found(SPIRV-Tools)
+_Vulkan_set_library_component_found(volk)
+_Vulkan_set_library_component_found(dxc)
if(Vulkan_MoltenVK_INCLUDE_DIR AND Vulkan_MoltenVK_LIBRARY)
set(Vulkan_MoltenVK_FOUND TRUE)
@@ -752,6 +831,44 @@ if(Vulkan_FOUND)
IMPORTED_LOCATION_DEBUG "${Vulkan_SPIRV-Tools_DEBUG_LIBRARY}")
endif()
endif()
+
+ if(Vulkan_volk_LIBRARY AND NOT TARGET Vulkan::volk)
+ add_library(Vulkan::volk STATIC IMPORTED)
+ set_property(TARGET Vulkan::volk
+ PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_CONFIGURATIONS Release)
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_LOCATION_RELEASE "${Vulkan_volk_LIBRARY}")
+
+ if (NOT WIN32)
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_LINK_INTERFACE_LIBRARIES dl)
+ endif()
+ endif()
+
+ if (Vulkan_dxc_LIBRARY AND NOT TARGET Vulkan::dxc_lib)
+ add_library(Vulkan::dxc_lib STATIC IMPORTED)
+ set_property(TARGET Vulkan::dxc_lib
+ PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
+ set_property(TARGET Vulkan::dxc_lib APPEND
+ PROPERTY
+ IMPORTED_CONFIGURATIONS Release)
+ set_property(TARGET Vulkan::dxc_lib APPEND
+ PROPERTY
+ IMPORTED_LOCATION_RELEASE "${Vulkan_dxc_LIBRARY}")
+ endif()
+
+ if(Vulkan_dxc_EXECUTABLE AND NOT TARGET Vulkan::dxc_exe)
+ add_executable(Vulkan::dxc_exe IMPORTED)
+ set_property(TARGET Vulkan::dxc_exe PROPERTY IMPORTED_LOCATION "${Vulkan_dxc_EXECUTABLE}")
+ endif()
+
endif()
if(Vulkan_MoltenVK_FOUND)
diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake
index 00729bc27..7118df200 100644
--- a/Modules/FindXCTest.cmake
+++ b/Modules/FindXCTest.cmake
@@ -13,7 +13,7 @@ An XCTest bundle is a CFBundle with a special product-type
and bundle extension. The Mac Developer Library provides more
information in the `Testing with Xcode`_ document.
-.. _Testing with Xcode: http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/
+.. _Testing with Xcode: https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/
Module Functions
^^^^^^^^^^^^^^^^
diff --git a/Modules/FindwxWindows.cmake b/Modules/FindwxWindows.cmake
index 07fbc1bff..2d46dbd53 100644
--- a/Modules/FindwxWindows.cmake
+++ b/Modules/FindwxWindows.cmake
@@ -79,8 +79,7 @@ DEPRECATED
-AUTHOR Jan Woetzel <http://www.mip.informatik.uni-kiel.de/~jw>
-(07/2003-01/2006)
+AUTHOR Jan Woetzel (07/2003-01/2006)
#]=======================================================================]
# ------------------------------------------------------------------
diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake
index 53df01a9d..af025afc8 100644
--- a/Modules/FortranCInterface.cmake
+++ b/Modules/FortranCInterface.cmake
@@ -361,10 +361,10 @@ function(FortranCInterface_VERIFY)
# Build a sample project which reports symbols.
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
try_compile(FortranCInterface_VERIFY_${lang}_COMPILED
- ${FortranCInterface_BINARY_DIR}/Verify${lang}
- ${FortranCInterface_SOURCE_DIR}/Verify
- VerifyFortranC # project name
- VerifyFortranC # target name
+ PROJECT VerifyFortranC
+ TARGET VerifyFortranC
+ SOURCE_DIR ${FortranCInterface_SOURCE_DIR}/Verify
+ BINARY_DIR ${FortranCInterface_BINARY_DIR}/Verify${lang}
CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx}
-DCMAKE_VERBOSE_MAKEFILE=ON
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake
index 567fc3727..6401aed1c 100644
--- a/Modules/FortranCInterface/Detect.cmake
+++ b/Modules/FortranCInterface/Detect.cmake
@@ -47,10 +47,10 @@ unset(_FortranCInterface_CMP0056)
# Build a sample project which reports symbols.
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
try_compile(FortranCInterface_COMPILED
- ${FortranCInterface_BINARY_DIR}
- ${FortranCInterface_SOURCE_DIR}
- FortranCInterface # project name
- FortranCInterface # target name
+ PROJECT FortranCInterface
+ TARGET FortranCInterface
+ SOURCE_DIR ${FortranCInterface_SOURCE_DIR}
+ BINARY_DIR ${FortranCInterface_BINARY_DIR}
CMAKE_FLAGS
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
"-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index f5f4f0238..b8dc482ee 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -348,7 +348,7 @@ function(gtest_add_tests)
unset(testList)
set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*")
- set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)")
+ set(gtest_test_type_regex "(TYPED_TEST|TEST)_?[FP]?")
foreach(source IN LISTS ARGS_SOURCES)
if(NOT ARGS_SKIP_DEPENDENCY)
@@ -361,7 +361,9 @@ function(gtest_add_tests)
# Parameterized tests have a different signature for the filter
if("x${test_type}" STREQUAL "xTEST_P")
- string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit})
+ string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit})
+ elseif("x${test_type}" STREQUAL "xTYPED_TEST_P")
+ string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1/*.\\2" gtest_test_name ${hit})
elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST")
string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit})
elseif("x${test_type}" STREQUAL "xTYPED_TEST")
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 958a6dbd7..38e32c282 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -37,8 +37,8 @@ endfunction()
#extract library name and version for given shared object
function(extract_so_info shared_object libname version)
- if(READELF_EXECUTABLE)
- execute_process(COMMAND "${READELF_EXECUTABLE}" -d "${shared_object}"
+ if(CPACK_READELF_EXECUTABLE)
+ execute_process(COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
@@ -197,15 +197,15 @@ function(cpack_deb_prepare_package_vars)
endforeach()
endif()
- find_program(READELF_EXECUTABLE NAMES readelf)
+ find_program(CPACK_READELF_EXECUTABLE NAMES readelf)
if(CPACK_DEBIAN_DEBUGINFO_PACKAGE AND CPACK_DEB_UNSTRIPPED_FILES)
- find_program(OBJCOPY_EXECUTABLE NAMES objcopy)
+ find_program(CPACK_OBJCOPY_EXECUTABLE NAMES objcopy)
- if(NOT OBJCOPY_EXECUTABLE)
+ if(NOT CPACK_OBJCOPY_EXECUTABLE)
message(FATAL_ERROR "debuginfo packages require the objcopy tool")
endif()
- if(NOT READELF_EXECUTABLE)
+ if(NOT CPACK_READELF_EXECUTABLE)
message(FATAL_ERROR "debuginfo packages require the readelf tool")
endif()
@@ -213,7 +213,7 @@ function(cpack_deb_prepare_package_vars)
foreach(_FILE IN LISTS CPACK_DEB_UNSTRIPPED_FILES)
# Get the file's Build ID
- execute_process(COMMAND env LC_ALL=C ${READELF_EXECUTABLE} -n "${_FILE}"
+ execute_process(COMMAND env LC_ALL=C ${CPACK_READELF_EXECUTABLE} -n "${_FILE}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE READELF_OUTPUT
RESULT_VARIABLE READELF_RESULT
@@ -221,7 +221,7 @@ function(cpack_deb_prepare_package_vars)
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT READELF_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: readelf: '${READELF_ERROR}';\n"
- "executed command: '${READELF_EXECUTABLE} -n ${_FILE}'")
+ "executed command: '${CPACK_READELF_EXECUTABLE} -n ${_FILE}'")
endif()
if(READELF_OUTPUT MATCHES "Build ID: ([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z]*)")
set(_BUILD_ID_START ${CMAKE_MATCH_1})
@@ -235,7 +235,7 @@ function(cpack_deb_prepare_package_vars)
set(_FILE_DBGSYM ${_DBGSYM_ROOT}/usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug)
get_filename_component(_OUT_DIR "${_FILE_DBGSYM}" DIRECTORY)
file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/${_OUT_DIR}")
- execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
+ execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
@@ -243,9 +243,9 @@ function(cpack_deb_prepare_package_vars)
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
- "executed command: '${OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'")
+ "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'")
endif()
- execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE}
+ execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
@@ -253,9 +253,9 @@ function(cpack_deb_prepare_package_vars)
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
- "executed command: '${OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'")
+ "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'")
endif()
- execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
+ execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
@@ -263,7 +263,7 @@ function(cpack_deb_prepare_package_vars)
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
- "executed command: '${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'")
+ "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'")
endif()
endforeach()
endif()
@@ -652,7 +652,7 @@ function(cpack_deb_prepare_package_vars)
unset(CPACK_DEBIAN_PACKAGE_SHLIBS_LIST)
if(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
- if(READELF_EXECUTABLE)
+ if(CPACK_READELF_EXECUTABLE)
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
extract_so_info("${_FILE}" libname soversion)
if(libname AND DEFINED soversion)
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index cd631b8ad..7c10280a9 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -625,8 +625,8 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR)
endif()
# With objdump we should check the debug symbols
- find_program(OBJDUMP_EXECUTABLE objdump)
- if(NOT OBJDUMP_EXECUTABLE)
+ find_program(CPACK_OBJDUMP_EXECUTABLE objdump)
+ if(NOT CPACK_OBJDUMP_EXECUTABLE)
message(FATAL_ERROR "CPackRPM: objdump binary could not be found!"
" Required for debuginfo packaging. See documentation of"
" CPACK_RPM_DEBUGINFO_PACKAGE variable for details.")
@@ -649,7 +649,7 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR)
continue()
endif()
- execute_process(COMMAND "${OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F}
+ execute_process(COMMAND "${CPACK_OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F}
WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}"
RESULT_VARIABLE OBJDUMP_EXEC_RESULT
OUTPUT_VARIABLE OBJDUMP_OUT
diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake
index 27aa3e017..eadf3da50 100644
--- a/Modules/Internal/CheckSourceCompiles.cmake
+++ b/Modules/Internal/CheckSourceCompiles.cmake
@@ -86,15 +86,13 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var)
else()
set(CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES)
endif()
- file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}"
- "${_source}\n")
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_START "Performing Test ${_var}")
endif()
+ string(APPEND _source "\n")
try_compile(${_var}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}
+ SOURCE_FROM_VAR "src.${_SRC_EXT}" _source
COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS}
${CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES}
diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake
index 75e98960f..09c85c5d3 100644
--- a/Modules/Internal/CheckSourceRuns.cmake
+++ b/Modules/Internal/CheckSourceRuns.cmake
@@ -85,15 +85,13 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var)
else()
set(CHECK_${_lang}_SOURCE_COMPILES_ADD_INCLUDES)
endif()
- file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}"
- "${_source}\n")
if(NOT CMAKE_REQUIRED_QUIET)
message(CHECK_START "Performing Test ${_var}")
endif()
+ string(APPEND _source "\n")
try_run(${_var}_EXITCODE ${_var}_COMPILED
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}
+ SOURCE_FROM_VAR "src.${_SRC_EXT}" _source
COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS}
${CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES}
diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake
index b6f3c091d..5c144ec51 100644
--- a/Modules/Internal/FeatureTesting.cmake
+++ b/Modules/Internal/FeatureTesting.cmake
@@ -4,7 +4,7 @@ macro(_record_compiler_features lang compile_flags feature_list)
string(TOLOWER ${lang} lang_lc)
file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin")
- file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "
+ set(_content "
const char features[] = {\"\\n\"\n")
get_property(known_features GLOBAL PROPERTY CMAKE_${lang}_KNOWN_FEATURES)
@@ -16,10 +16,11 @@ macro(_record_compiler_features lang compile_flags feature_list)
else()
set(_feature_condition "#if ${_cmake_feature_test_${feature}}\n\"1\"\n#else\n\"0\"\n#endif\n")
endif()
- file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n")
+ string(APPEND _content
+ "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n")
endif()
endforeach()
- file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
+ string(APPEND _content
"\n};\n\nint main(int argc, char** argv) { (void)argv; return features[argc]; }\n")
if(CMAKE_${lang}_LINK_WITH_STANDARD_COMPILE_OPTION)
@@ -31,7 +32,7 @@ macro(_record_compiler_features lang compile_flags feature_list)
endif()
try_compile(CMAKE_${lang}_FEATURE_TEST
- ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
+ SOURCE_FROM_VAR "feature_tests.${lang_lc}" _content
COMPILE_DEFINITIONS "${compile_flags}"
LINK_LIBRARIES "${compile_flags_for_link}"
OUTPUT_VARIABLE _output
diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake
index 5a532c7cc..a9aa8e022 100644
--- a/Modules/Platform/AIX-GNU.cmake
+++ b/Modules/Platform/AIX-GNU.cmake
@@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endmacro()
diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake
index 2a8c159af..902cbb3aa 100644
--- a/Modules/Platform/AIX-XL.cmake
+++ b/Modules/Platform/AIX-XL.cmake
@@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS>${_OBJECTS}"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS>${_OBJECTS}"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
unset(_OBJECTS)
diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList
index 891bce76d..5e16fcb4c 100755
--- a/Modules/Platform/AIX/ExportImportList
+++ b/Modules/Platform/AIX/ExportImportList
@@ -5,7 +5,7 @@
# This script is internal to CMake and meant only to be
# invoked by CMake-generated build systems on AIX.
-usage='usage: ExportImportList -o <out-file> [-l <lib>] [-n] [--] <objects>...'
+usage='usage: ExportImportList -o <out-file> -c <compiler> [-l <lib>] [-n] [--] <objects>...'
die() {
echo "$@" 1>&2; exit 1
@@ -15,11 +15,13 @@ die() {
out=''
lib=''
no_objects=''
+compiler=''
while test "$#" != 0; do
case "$1" in
-l) shift; lib="$1" ;;
-o) shift; out="$1" ;;
-n) no_objects='1' ;;
+ -c) shift; compiler="$1" ;;
--) shift; break ;;
-*) die "$usage" ;;
*) break ;;
@@ -27,27 +29,47 @@ while test "$#" != 0; do
shift
done
test -n "$out" || die "$usage"
+# We need the compiler executable to resolve where the ibm-llvm-nm executable is
+test -n "$compiler" || die "$usage"
# Build a temporary file that atomically replaces the output later.
out_tmp="$out.tmp$$"
trap 'rm -f "$out_tmp"' EXIT INT TERM
> "$out_tmp"
+# If IPA was enabled and a compiler from the IBMClang family is used, then
+# the object files contain LLVM bitcode[0] rather than XCOFF objects and so
+# need to be handled differently.
+#
+# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto
+NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm"
+
+function IsBitcode {
+ # N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset
+ # cut: trim off the preceding whitespace where the offset would be
+ # 4243code is the hexadecimal magic number for LLVM bitcode
+ [ "$(od -N4 -tx -An $1 | cut -d ' ' -f 2)" == "4243c0de" ];
+}
+
# Collect symbols exported from all object files.
if test -z "$no_objects"; then
for f in "$@"; do
- dump -tov -X 32_64 "$f" |
- awk '
- BEGIN {
- V["EXPORTED"]=" export"
- V["PROTECTED"]=" protected"
- }
- /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
- if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
- print $NF V[$(NF-1)]
+ if IsBitcode "$f"; then
+ "$NM" "$f" --defined-only --extern-only --just-symbol-name 2>/dev/null
+ else
+ dump -tov -X 32_64 "$f" |
+ awk '
+ BEGIN {
+ V["EXPORTED"]=" export"
+ V["PROTECTED"]=" protected"
+ }
+ /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
+ if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
+ print $NF V[$(NF-1)]
+ }
}
- }
- '
+ '
+ fi
done >> "$out_tmp"
fi
diff --git a/Modules/Platform/DragonFly.cmake b/Modules/Platform/DragonFly.cmake
index 12e5f3ccc..994ba7931 100644
--- a/Modules/Platform/DragonFly.cmake
+++ b/Modules/Platform/DragonFly.cmake
@@ -3,6 +3,7 @@
# see http://archive.netbsd.se/?ml=dfbsd-users&a=2007-07&m=4678361
include(Platform/FreeBSD)
+set(BSD "DragonFlyBSD")
# DragonFly BSD requires -z origin to enable $ORIGIN expansion in RPATH.
# This is not required for FreeBSD since 10.2-RELEASE.
diff --git a/Modules/Platform/FreeBSD.cmake b/Modules/Platform/FreeBSD.cmake
index bd5a78638..9cd93998f 100644
--- a/Modules/Platform/FreeBSD.cmake
+++ b/Modules/Platform/FreeBSD.cmake
@@ -1,3 +1,4 @@
+set(BSD "FreeBSD")
set(CMAKE_DL_LIBS "")
set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC")
set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE")
diff --git a/Modules/Platform/Linux-IntelLLVM.cmake b/Modules/Platform/Linux-IntelLLVM.cmake
index 1363b4427..992f80e07 100644
--- a/Modules/Platform/Linux-IntelLLVM.cmake
+++ b/Modules/Platform/Linux-IntelLLVM.cmake
@@ -8,18 +8,6 @@ if(__LINUX_COMPILER_INTEL_LLVM)
endif()
set(__LINUX_COMPILER_INTEL_LLVM 1)
-if(NOT XIAR)
- set(_intel_xiar_hints)
- foreach(lang C CXX Fortran)
- if(IS_ABSOLUTE "${CMAKE_${lang}_COMPILER}")
- get_filename_component(_hint "${CMAKE_${lang}_COMPILER}" PATH)
- list(APPEND _intel_xiar_hints ${_hint})
- endif()
- endforeach()
- find_program(XIAR NAMES xiar HINTS ${_intel_xiar_hints})
- mark_as_advanced(XIAR)
-endif()
-
macro(__linux_compiler_intel_llvm lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
@@ -37,19 +25,5 @@ macro(__linux_compiler_intel_llvm lang)
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
- set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
-
- if(XIAR)
- # INTERPROCEDURAL_OPTIMIZATION
- set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo)
- set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO
- "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> "
- "${XIAR} -s <TARGET> ")
- set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
- set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES)
- else()
- set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
- endif()
-
set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
endmacro()
diff --git a/Modules/Platform/Linux-NVHPC.cmake b/Modules/Platform/Linux-NVHPC.cmake
index aad17f1e9..602b41782 100644
--- a/Modules/Platform/Linux-NVHPC.cmake
+++ b/Modules/Platform/Linux-NVHPC.cmake
@@ -3,13 +3,15 @@
# This module is shared by multiple languages; use include blocker.
-if(__LINUX_COMPILER_NVIDIA)
- return()
-endif()
-set(__LINUX_COMPILER_NVIDIA 1)
-
-include(Platform/Linux-PGI)
+include_guard()
macro(__linux_compiler_nvhpc lang)
- __linux_compiler_pgi(${lang})
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+ set(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER YES)
+ set(CMAKE_${lang}_LINK_OPTIONS_PIE "-fPIE")
+ set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
+ set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+ set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "")
endmacro()
diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake
index a7e58ab49..3dc3ca359 100644
--- a/Modules/Platform/Linux.cmake
+++ b/Modules/Platform/Linux.cmake
@@ -1,3 +1,4 @@
+set(LINUX 1)
set(CMAKE_DL_LIBS "dl")
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
@@ -86,7 +87,12 @@ include(Platform/UnixPaths)
# Debian has lib32 and lib64 paths only for compatibility so they should not be
# searched.
-if(NOT CMAKE_CROSSCOMPILING AND EXISTS "/etc/debian_version")
- set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS FALSE)
- set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+if(NOT CMAKE_CROSSCOMPILING)
+ if (EXISTS "/etc/debian_version")
+ set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS FALSE)
+ set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+ endif()
+ if (EXISTS "/etc/arch-release")
+ set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+ endif()
endif()
diff --git a/Modules/Platform/NetBSD.cmake b/Modules/Platform/NetBSD.cmake
index ab859239f..52c65942f 100644
--- a/Modules/Platform/NetBSD.cmake
+++ b/Modules/Platform/NetBSD.cmake
@@ -1,3 +1,4 @@
+set(BSD "NetBSD")
set(CMAKE_DL_LIBS "")
set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC")
set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE")
diff --git a/Modules/Platform/OpenBSD.cmake b/Modules/Platform/OpenBSD.cmake
index 97e2a6a83..51ea60dff 100644
--- a/Modules/Platform/OpenBSD.cmake
+++ b/Modules/Platform/OpenBSD.cmake
@@ -1,4 +1,5 @@
include(Platform/NetBSD)
+set(BSD "OpenBSD")
# On OpenBSD, the compile time linker does not share it's configuration with
# the runtime linker. This will extract the library search paths from the
diff --git a/Modules/Platform/SerenityOS-Clang-ASM.cmake b/Modules/Platform/SerenityOS-Clang-ASM.cmake
new file mode 100644
index 000000000..ba1e18cfe
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-ASM.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(ASM)
diff --git a/Modules/Platform/SerenityOS-Clang-C.cmake b/Modules/Platform/SerenityOS-Clang-C.cmake
new file mode 100644
index 000000000..791a1978d
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(C)
diff --git a/Modules/Platform/SerenityOS-Clang-CXX.cmake b/Modules/Platform/SerenityOS-Clang-CXX.cmake
new file mode 100644
index 000000000..084e319fa
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(CXX)
diff --git a/Modules/Platform/SerenityOS-GNU-ASM.cmake b/Modules/Platform/SerenityOS-GNU-ASM.cmake
new file mode 100644
index 000000000..ba1e18cfe
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-ASM.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(ASM)
diff --git a/Modules/Platform/SerenityOS-GNU-C.cmake b/Modules/Platform/SerenityOS-GNU-C.cmake
new file mode 100644
index 000000000..791a1978d
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(C)
diff --git a/Modules/Platform/SerenityOS-GNU-CXX.cmake b/Modules/Platform/SerenityOS-GNU-CXX.cmake
new file mode 100644
index 000000000..084e319fa
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(CXX)
diff --git a/Modules/Platform/SerenityOS-GNU.cmake b/Modules/Platform/SerenityOS-GNU.cmake
new file mode 100644
index 000000000..ed39477a8
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU.cmake
@@ -0,0 +1,24 @@
+# This module is shared by multiple languages; use include blocker.
+include_guard()
+
+set(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code,-z,max-page-size=0x1000")
+
+macro(__serenity_compiler_gnu lang)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-rpath,")
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
+ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_${lang}_FLAG "-Wl,-rpath-link,")
+ set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,")
+ set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-dynamic")
+
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared -Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code")
+
+ # Initialize link type selection flags. These flags are used when
+ # building a shared library, shared module, or executable that links
+ # to other libraries to select whether to use the static or shared
+ # versions of the libraries.
+ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
+ set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic")
+ set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
+ endforeach()
+
+endmacro()
diff --git a/Modules/Platform/SerenityOS.cmake b/Modules/Platform/SerenityOS.cmake
new file mode 100644
index 000000000..dc4f369dc
--- /dev/null
+++ b/Modules/Platform/SerenityOS.cmake
@@ -0,0 +1,12 @@
+
+set(SERENITYOS 1)
+
+set(CMAKE_DL_LIBS "")
+set(CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "\$ORIGIN")
+set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
+
+# Shared libraries with no builtin soname may not be linked safely by
+# specifying the file path.
+set(CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME 1)
+
+include(Platform/UnixPaths)
diff --git a/Modules/Platform/Windows-Clang-HIP.cmake b/Modules/Platform/Windows-Clang-HIP.cmake
new file mode 100644
index 000000000..20879fabe
--- /dev/null
+++ b/Modules/Platform/Windows-Clang-HIP.cmake
@@ -0,0 +1,19 @@
+include(Platform/Windows-Clang)
+set(_COMPILE_HIP_MSVC " -TP")
+__windows_compiler_clang(HIP)
+
+if("x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_HIP)
+ set(CMAKE_HIP_DEPENDS_USE_COMPILER TRUE)
+ endif()
+elseif("x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_HIP)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_HIP_DEPFILE_FORMAT gcc)
+ set(CMAKE_HIP_DEPENDS_USE_COMPILER TRUE)
+ endif()
+endif()
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index 39413114b..33d271de8 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -89,17 +89,27 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd)
if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
- set(__ADDED_FLAGS "")
- set(__ADDED_FLAGS_DEBUG "")
+ set(_RTL_FLAGS "")
+ set(_RTL_FLAGS_DEBUG "")
else()
- set(__ADDED_FLAGS_DEBUG "-D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd")
- set(__ADDED_FLAGS "-D_DLL -D_MT -Xclang --dependent-lib=msvcrt")
+ set(_RTL_FLAGS_DEBUG " -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd")
+ set(_RTL_FLAGS " -D_DLL -D_MT -Xclang --dependent-lib=msvcrt")
endif()
- string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -Xclang -gcodeview -O0 ${__ADDED_FLAGS_DEBUG}")
- string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG ${__ADDED_FLAGS}")
- string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG ${__ADDED_FLAGS}")
- string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG -Xclang -gcodeview ${__ADDED_FLAGS}")
+ if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
+ set(_DBG_FLAGS "")
+ else()
+ set(_DBG_FLAGS " -g -Xclang -gcodeview")
+ endif()
+
+ string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -O0${_DBG_FLAGS}${_RTL_FLAGS_DEBUG}")
+ string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG${_RTL_FLAGS}")
+ string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG${_RTL_FLAGS}")
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -DNDEBUG${_DBG_FLAGS}${_RTL_FLAGS}")
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -g -Xclang -gcodeview)
+ #set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase) # not supported by Clang
+ #set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # not supported by Clang
endif()
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
@@ -109,8 +119,9 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>)
set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER> -x ${__pch_header_${lang}})
- unset(__ADDED_FLAGS)
- unset(__ADDED_FLAGS_DEBUG)
+ unset(_DBG_FLAGS)
+ unset(_RTL_FLAGS)
+ unset(_RTL_FLAGS_DEBUG)
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER)
set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames")
@@ -146,24 +157,36 @@ macro(__enable_llvm_rc_preprocessing clang_option_prefix extra_pp_flags)
endif()
endmacro()
+macro(__verify_same_language_values variable)
+ foreach(lang "C" "CXX" "HIP")
+ if(DEFINED CMAKE_${lang}_${variable})
+ list(APPEND __LANGUAGE_VALUES_${variable} "${CMAKE_${lang}_${variable}}")
+ endif()
+ endforeach()
+ list(REMOVE_DUPLICATES __LANGUAGE_VALUES_${variable})
+ list(LENGTH __LANGUAGE_VALUES_${variable} __NUM_VALUES)
+
+ if(__NUM_VALUES GREATER 1)
+ message(FATAL_ERROR ${ARGN})
+ endif()
+ unset(__NUM_VALUES)
+ unset(__LANGUAGE_VALUES_${variable})
+endmacro()
if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
- OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"
+ OR "x${CMAKE_HIP_SIMULATE_ID}" STREQUAL "xMSVC")
- if ( DEFINED CMAKE_C_COMPILER_ID AND DEFINED CMAKE_CXX_COMPILER_ID
- AND NOT "x${CMAKE_C_COMPILER_ID}" STREQUAL "x${CMAKE_CXX_COMPILER_ID}")
- message(FATAL_ERROR "The current configuration mixes Clang and MSVC or "
- "some other CL compatible compiler tool. This is not supported. "
- "Use either clang or MSVC as both C and C++ compilers.")
- endif()
+ __verify_same_language_values(COMPILER_ID
+ "The current configuration mixes Clang and MSVC or "
+ "some other CL compatible compiler tool. This is not supported. "
+ "Use either clang or MSVC as both C, C++ and/or HIP compilers.")
- if ( DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT AND DEFINED CMAKE_CXX_COMPILER_FRONTEND_VARIANT
- AND NOT "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}")
- message(FATAL_ERROR "The current configuration uses the Clang compiler "
- "tool with mixed frontend variants, both the GNU and in MSVC CL "
- "like variants. This is not supported. Use either clang/clang++ "
- "or clang-cl as both C and C++ compilers.")
- endif()
+ __verify_same_language_values(COMPILER_FRONTEND_VARIANT
+ "The current configuration uses the Clang compiler "
+ "tool with mixed frontend variants, both the GNU and in MSVC CL "
+ "like variants. This is not supported. Use either clang/clang++ "
+ "or clang-cl as both C, C++ and/or HIP compilers.")
if(NOT CMAKE_RC_COMPILER_INIT)
# Check if rc is already in the path
@@ -183,13 +206,17 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
unset(__RC_COMPILER_PATH CACHE)
endif()
- if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" )
+ if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC"
+ OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC"
+ OR "x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+
include(Platform/Windows-MSVC)
# Set the clang option forwarding prefix for clang-cl usage in the llvm-rc processing stage
__enable_llvm_rc_preprocessing("-clang:" "")
macro(__windows_compiler_clang_base lang)
set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}")
__windows_compiler_msvc(${lang})
+ unset(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # -ZI not supported by Clang
set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX")
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc")
endmacro()
@@ -202,6 +229,14 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
endif()
unset(__WINDOWS_CLANG_CMP0091)
+ cmake_policy(GET CMP0141 __WINDOWS_MSVC_CMP0141)
+ if(__WINDOWS_MSVC_CMP0141 STREQUAL "NEW")
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>")
+ else()
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "")
+ endif()
+ unset(__WINDOWS_MSVC_CMP0141)
+
set(CMAKE_BUILD_TYPE_INIT Debug)
__enable_llvm_rc_preprocessing("" "-x c")
diff --git a/Modules/Platform/Windows-Intel-C.cmake b/Modules/Platform/Windows-Intel-C.cmake
index e4d9b93ee..8ae685293 100644
--- a/Modules/Platform/Windows-Intel-C.cmake
+++ b/Modules/Platform/Windows-Intel-C.cmake
@@ -19,9 +19,8 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
endif()
-if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ")
- # The Intel compiler does not properly escape spaces in a depfile.
- # Fall back to msvc depfile format.
- set(CMAKE_DEPFILE_FLAGS_C "/showIncludes")
- set(CMAKE_C_DEPFILE_FORMAT msvc)
-endif()
+# The Intel compiler does not properly escape spaces in a depfile which can
+# occur in source and binary cmake paths as well as external include paths.
+# Until Intel fixes this bug, fall back unconditionally to msvc depfile format.
+set(CMAKE_DEPFILE_FLAGS_C "/showIncludes")
+set(CMAKE_C_DEPFILE_FORMAT msvc)
diff --git a/Modules/Platform/Windows-Intel-CXX.cmake b/Modules/Platform/Windows-Intel-CXX.cmake
index 6adbb6e19..e2fa2afaa 100644
--- a/Modules/Platform/Windows-Intel-CXX.cmake
+++ b/Modules/Platform/Windows-Intel-CXX.cmake
@@ -20,9 +20,8 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
endif()
-if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ")
- # The Intel compiler does not properly escape spaces in a depfile.
- # Fall back to msvc depfile format.
- set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes")
- set(CMAKE_CXX_DEPFILE_FORMAT msvc)
-endif()
+# The Intel compiler does not properly escape spaces in a depfile which can
+# occur in source and binary cmake paths as well as external include paths.
+# Until Intel fixes this bug, fall back unconditionally to msvc depfile format.
+set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes")
+set(CMAKE_CXX_DEPFILE_FORMAT msvc)
diff --git a/Modules/Platform/Windows-Intel-Fortran.cmake b/Modules/Platform/Windows-Intel-Fortran.cmake
index e3804fb86..c9b70d59b 100644
--- a/Modules/Platform/Windows-Intel-Fortran.cmake
+++ b/Modules/Platform/Windows-Intel-Fortran.cmake
@@ -33,6 +33,8 @@ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -th
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll)
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs)
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi)
# Intel Fortran for Windows supports single-threaded RTL but it is
# not implemented by the Visual Studio integration.
diff --git a/Modules/Platform/Windows-IntelLLVM-Fortran.cmake b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake
index 06d0a00d1..202ba23d0 100644
--- a/Modules/Platform/Windows-IntelLLVM-Fortran.cmake
+++ b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake
@@ -33,6 +33,8 @@ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -th
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll)
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs)
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi)
# Intel Fortran for Windows supports single-threaded RTL but it is
# not implemented by the Visual Studio integration.
diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake
index f24dcdb1c..43f5874e2 100644
--- a/Modules/Platform/Windows-IntelLLVM.cmake
+++ b/Modules/Platform/Windows-IntelLLVM.cmake
@@ -3,26 +3,61 @@
# This module is shared by multiple languages; use include blocker.
-if(__WINDOWS_INTEL)
+if(__WINDOWS_INTEL_LLVM)
return()
endif()
-set(__WINDOWS_INTEL 1)
+set(__WINDOWS_INTEL_LLVM 1)
+# Platform/Windows-MSVC adds some linking options icx/ifx do not understand,
+# but that need to be passed to the linker. Wrap all the linking options from
+# Platform/Windows-MSVC so that the compiler will hand them off to the linker
+# without interpreting them.
+
+# Save original CMAKE_${t}_LINKER_FLAGS_INIT
+foreach(t EXE SHARED MODULE STATIC)
+ set(_saved_cmake_${t}_linker_flags_init ${CMAKE_${t}_LINKER_FLAGS_INIT})
+ set(CMAKE_${t}_LINKER_FLAGS_INIT "")
+endforeach()
include(Platform/Windows-MSVC)
+# Wrap linker flags from Windows-MSVC
+set(_IntelLLVM_LINKER_WRAPPER_FLAG "/Qoption,link,")
+set(_IntelLLVM_LINKER_WRAPPER_FLAG_SEP ",")
+foreach(t EXE SHARED MODULE STATIC)
+ set(_wrapped_linker_flags "")
+ foreach(flag ${CMAKE_${t}_LINKER_FLAGS_INIT})
+ string(STRIP ${flag} flag)
+ list(APPEND _wrapped_linker_flags "${_IntelLLVM_LINKER_WRAPPER_FLAG}${flag}")
+ endforeach()
+ set(CMAKE_${t}_LINKER_FLAGS_INIT "")
+ list(APPEND CMAKE_${t}_LINKER_FLAGS_INIT
+ ${_saved_cmake_${t}_linker_flags_init} ${_wrapped_linker_flags})
+endforeach()
+
macro(__windows_compiler_intel lang)
__windows_compiler_msvc(${lang})
- # For DPCPP other offload cases, some link flags need to go to the compiler
- # driver and others need to go to the linker. Pass the compiler linking flags
- # in CMAKE_${lang}_LINK_FLAGS and linker flags in LINK_FLAGS
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "${_IntelLLVM_LINKER_WRAPPER_FLAG}")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP "${_IntelLLVM_LINKER_WRAPPER_FLAG_SEP}")
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:windows")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:console")
+ set(CMAKE_LINK_DEF_FILE_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/DEF:")
+ set(CMAKE_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/LIBPATH:")
+
+ # Features for LINK_LIBRARY generator expression
+ if(MSVC_VERSION GREATER "1900")
+ ## WHOLE_ARCHIVE: Force loading all members of an archive
+ set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>")
+ set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+ endif()
+
set(CMAKE_${lang}_LINK_EXECUTABLE
- "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
+ "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <LINK_LIBRARIES> /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+ "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD <LINK_FLAGS> <LINK_LIBRARIES> -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1)
# The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
- "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> -link <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+ "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
endif()
set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index e74ec9e7f..8e96bf449 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -331,6 +331,13 @@ else()
endif()
unset(__WINDOWS_MSVC_CMP0091)
+cmake_policy(GET CMP0141 __WINDOWS_MSVC_CMP0141)
+if(__WINDOWS_MSVC_CMP0141 STREQUAL "NEW")
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>")
+else()
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "")
+endif()
+unset(__WINDOWS_MSVC_CMP0141)
# Features for LINK_LIBRARY generator expression
if(MSVC_VERSION GREATER "1900")
@@ -441,6 +448,12 @@ macro(__windows_compiler_msvc lang)
endif()
unset(_cmp0092)
+ if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
+ set(_Zi "")
+ else()
+ set(_Zi " /Zi")
+ endif()
+
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
# note: MSVC 14 2015 Update 1 sets -fno-ms-compatibility by default, but this does not allow one to compile many projects
# that include MS's own headers. CMake itself is affected project too.
@@ -451,20 +464,24 @@ macro(__windows_compiler_msvc lang)
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} -DNDEBUG") # TODO: Add '-Os' once VS generator maps it properly for Clang
else()
string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} /D_WINDOWS${_W3}${_FLAGS_${lang}}")
- string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} /Zi /Ob0 /Od ${_RTC1}")
+ string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd}${_Zi} /Ob0 /Od ${_RTC1}")
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT "${_MD} /O2 /Ob2 /DNDEBUG")
- string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD} /Zi /O2 /Ob1 /DNDEBUG")
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD}${_Zi} /O2 /Ob1 /DNDEBUG")
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} /O1 /Ob1 /DNDEBUG")
endif()
unset(_Wall)
unset(_W3)
unset(_MDd)
unset(_MD)
+ unset(_Zi)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -MT)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -MD)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -MTd)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -MDd)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue -ZI)
endif()
set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 6c1699b3c..326e7155d 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -57,6 +57,12 @@ else()
set(_MD "-MD ")
endif()
+if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
+ set(_Zi "")
+else()
+ set(_Zi " -Zi")
+endif()
+
cmake_policy(GET CMP0092 _cmp0092)
if(_cmp0092 STREQUAL "NEW")
set(_W3 "")
@@ -66,11 +72,12 @@ endif()
unset(_cmp0092)
string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"${_W3}${_FLAGS_CXX}\"")
-string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}-Zi -Ob0 -Od ${_RTC1}\"")
+string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}${_Zi} -Ob0 -Od ${_RTC1}\"")
string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"${_MD}-O2 -Ob2\" -DNDEBUG")
-string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"${_MD}-Zi -O2 -Ob1\" -DNDEBUG")
+string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"${_MD}${_Zi} -O2 -Ob1\" -DNDEBUG")
string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"${_MD}-O1 -Ob1\" -DNDEBUG")
unset(_W3)
+unset(_Zi)
unset(_MDd)
unset(_MD)
@@ -78,6 +85,9 @@ set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xcomp
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -Xcompiler=-MD)
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -Xcompiler=-MTd)
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -Xcompiler=-MDd)
+set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Xcompiler=-Z7)
+set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Xcompiler=-Zi)
+set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue -Xcompiler=-ZI)
set(CMAKE_CUDA_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
diff --git a/Modules/Platform/Windows.cmake b/Modules/Platform/Windows.cmake
index d8b395781..526316115 100644
--- a/Modules/Platform/Windows.cmake
+++ b/Modules/Platform/Windows.cmake
@@ -19,8 +19,8 @@ set(CMAKE_LINK_LIBRARY_SUFFIX ".lib")
set(CMAKE_DL_LIBS "")
set(CMAKE_EXTRA_LINK_EXTENSIONS ".targets")
-set(CMAKE_FIND_LIBRARY_PREFIXES "")
-set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
+set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
# for borland make long command lines are redirected to a file
# with the following syntax, see Windows-bcc32.cmake for use
diff --git a/Modules/Platform/kFreeBSD.cmake b/Modules/Platform/kFreeBSD.cmake
index c1db2594d..09c240dc5 100644
--- a/Modules/Platform/kFreeBSD.cmake
+++ b/Modules/Platform/kFreeBSD.cmake
@@ -1,4 +1,5 @@
-# kFreeBSD looks just like Linux.
+# kFreeBSD is a Debian GNU distribution with a kernel from FreeBSD,
+# and should be marked as LINUX
include(Platform/Linux)
set(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-kfreebsd-gnu[a-z0-9_]*")
diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake
index ea8ca73b3..096c90c3c 100644
--- a/Modules/TestBigEndian.cmake
+++ b/Modules/TestBigEndian.cmake
@@ -77,20 +77,16 @@ macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE)
endif()
if(_test_language STREQUAL "CXX")
- set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp")
+ set(_test_file TestEndianess.cpp)
else()
- set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c")
+ set(_test_file TestEndianess.c)
endif()
- configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in"
- ${_test_file}
- @ONLY)
-
- file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT)
+ file(READ "${CMAKE_ROOT}/Modules/TestEndianess.c.in" TEST_ENDIANESS_FILE_CONTENT)
+ string(CONFIGURE "${TEST_ENDIANESS_FILE_CONTENT}" TEST_ENDIANESS_FILE_CONTENT @ONLY)
try_compile(HAVE_${VARIABLE}
- "${CMAKE_BINARY_DIR}"
- ${_test_file}
+ SOURCE_FROM_VAR "${_test_file}" TEST_ENDIANESS_FILE_CONTENT
OUTPUT_VARIABLE OUTPUT
COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" )
@@ -131,12 +127,12 @@ macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE)
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Determining if the system is big endian passed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
+ "Determining if the system is big endian passed with the following output:\n${OUTPUT}\n${_test_file}:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
else()
message(CHECK_FAIL "failed")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining if the system is big endian failed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
+ "Determining if the system is big endian failed with the following output:\n${OUTPUT}\n${_test_file}:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
set(${VARIABLE})
endif()
endif()
diff --git a/Modules/TestCXXAcceptsFlag.cmake b/Modules/TestCXXAcceptsFlag.cmake
index ce505f3ce..2e511ae12 100644
--- a/Modules/TestCXXAcceptsFlag.cmake
+++ b/Modules/TestCXXAcceptsFlag.cmake
@@ -25,8 +25,7 @@ macro(CHECK_CXX_ACCEPTS_FLAG FLAGS VARIABLE)
if(NOT DEFINED ${VARIABLE})
message(CHECK_START "Checking to see if CXX compiler accepts flag ${FLAGS}")
try_compile(${VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/DummyCXXFile.cxx
+ SOURCES ${CMAKE_ROOT}/Modules/DummyCXXFile.cxx
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${FLAGS}
OUTPUT_VARIABLE OUTPUT)
if(${VARIABLE})
diff --git a/Modules/TestForANSIForScope.cmake b/Modules/TestForANSIForScope.cmake
index 0f2dc013d..06db586ff 100644
--- a/Modules/TestForANSIForScope.cmake
+++ b/Modules/TestForANSIForScope.cmake
@@ -17,8 +17,8 @@ for-init-statement to the loop body.
if(NOT DEFINED CMAKE_ANSI_FOR_SCOPE)
message(CHECK_START "Check for ANSI scope")
- try_compile(CMAKE_ANSI_FOR_SCOPE ${CMAKE_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx
+ try_compile(CMAKE_ANSI_FOR_SCOPE
+ SOURCES ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx
OUTPUT_VARIABLE OUTPUT)
if (CMAKE_ANSI_FOR_SCOPE)
message(CHECK_PASS "found")
diff --git a/Modules/TestForSSTREAM.cmake b/Modules/TestForSSTREAM.cmake
index 545b7ec29..9a09ac7f9 100644
--- a/Modules/TestForSSTREAM.cmake
+++ b/Modules/TestForSSTREAM.cmake
@@ -16,8 +16,8 @@ check if the compiler supports the standard ANSI sstream header
if(NOT DEFINED CMAKE_HAS_ANSI_STRING_STREAM)
message(CHECK_START "Check for sstream")
- try_compile(CMAKE_HAS_ANSI_STRING_STREAM ${CMAKE_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/TestForSSTREAM.cxx
+ try_compile(CMAKE_HAS_ANSI_STRING_STREAM
+ SOURCES ${CMAKE_ROOT}/Modules/TestForSSTREAM.cxx
OUTPUT_VARIABLE OUTPUT)
if (CMAKE_HAS_ANSI_STRING_STREAM)
message(CHECK_PASS "found")
diff --git a/Modules/TestForSTDNamespace.cmake b/Modules/TestForSTDNamespace.cmake
index d101c833e..cd9c7827c 100644
--- a/Modules/TestForSTDNamespace.cmake
+++ b/Modules/TestForSTDNamespace.cmake
@@ -16,8 +16,8 @@ check if the compiler supports std:: on stl classes
if(NOT DEFINED CMAKE_STD_NAMESPACE)
message(CHECK_START "Check for STD namespace")
- try_compile(CMAKE_STD_NAMESPACE ${CMAKE_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/TestForSTDNamespace.cxx
+ try_compile(CMAKE_STD_NAMESPACE
+ SOURCES ${CMAKE_ROOT}/Modules/TestForSTDNamespace.cxx
OUTPUT_VARIABLE OUTPUT)
if (CMAKE_STD_NAMESPACE)
message(CHECK_PASS "found")
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index ef63ac34b..1511bfd50 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -294,7 +294,7 @@ Header Generation
.. deprecated:: 3.11
This command will no longer be supported starting with version 10 of the JDK
- due to the `suppression of javah tool <http://openjdk.java.net/jeps/313>`_.
+ due to the `suppression of javah tool <https://openjdk.java.net/jeps/313>`_.
The :ref:`add_jar(GENERATE_NATIVE_HEADERS) <add_jar>` command should be
used instead.
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 35b1704ff..fd6596b85 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -377,6 +377,7 @@ set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs")
+set(SWIG_PERL_EXTRA_FILE_EXTENSIONS ".pm")
set(SWIG_MANAGE_SUPPORT_FILES_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UseSWIG/ManageSupportFiles.cmake")
@@ -989,6 +990,9 @@ function(SWIG_ADD_LIBRARY name)
endif()
set_target_properties (${target_name} PROPERTIES PREFIX "")
endif()
+ if (APPLE)
+ set_target_properties (${target_name} PROPERTIES SUFFIX ".dylib")
+ endif ()
else()
# assume empty prefix because we expect the module to be dynamically loaded
set_target_properties (${target_name} PROPERTIES PREFIX "")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 95b07cbc9..c268a9211 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -4,7 +4,7 @@
# To ensure maximum portability across various compilers and platforms
# deactivate any compiler extensions. Skip this for QNX, where additional
# work is needed to build without compiler extensions.
-if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
+if(NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_C_EXTENSIONS FALSE)
set(CMAKE_CXX_EXTENSIONS FALSE)
endif()
@@ -31,70 +31,48 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
set(CMake_USE_XCOFF_PARSER 1)
endif()
+# Watcom support
+if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(CMAKE_USE_WMAKE 1)
+endif()
+
+set(CMake_STAT_HAS_ST_MTIM ${KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED})
+set(CMake_STAT_HAS_ST_MTIMESPEC ${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED})
+
set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR})
if(WIN32)
# ensure Unicode friendly APIs are used on Windows
- add_definitions(-DUNICODE -D_UNICODE)
+ add_compile_definitions(UNICODE _UNICODE)
# minimize windows.h content
- add_definitions(-DWIN32_LEAN_AND_MEAN)
+ add_compile_definitions(WIN32_LEAN_AND_MEAN)
endif()
# configure the .dox.in file
if(CMake_BUILD_DEVELOPER_REFERENCE)
- configure_file(
- "${CMake_SOURCE_DIR}/Source/dir.dox.in"
- "${CMake_BINARY_DIR}/Source/dir.dox"
- @ONLY
- )
+ configure_file(dir.dox.in dir.dox @ONLY)
endif()
# configure the .h file
-configure_file(
- "${CMake_SOURCE_DIR}/Source/cmConfigure.cmake.h.in"
- "${CMake_BINARY_DIR}/Source/cmConfigure.h"
- )
-configure_file(
- "${CMake_SOURCE_DIR}/Source/cmVersionConfig.h.in"
- "${CMake_BINARY_DIR}/Source/cmVersionConfig.h"
- )
-configure_file(
- "${CMake_SOURCE_DIR}/Source/CPack/cmCPackConfigure.h.in"
- "${CMake_BINARY_DIR}/Source/CPack/cmCPackConfigure.h"
- )
+configure_file(cmConfigure.cmake.h.in cmConfigure.h)
+configure_file(cmVersionConfig.h.in cmVersionConfig.h)
# Tell CMake executable in the build tree where to find the source tree.
configure_file(
- "${CMake_SOURCE_DIR}/Source/CMakeSourceDir.txt.in"
- "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt" @ONLY
- )
-
-# add the include path to find the .h
-include_directories(
- "${CMake_BINARY_DIR}/Source"
- "${CMake_SOURCE_DIR}/Source"
- "${CMake_SOURCE_DIR}/Source/LexerParser"
- ${CMAKE_ZLIB_INCLUDES}
- ${CMAKE_EXPAT_INCLUDES}
- ${CMAKE_TAR_INCLUDES}
- ${CMake_HAIKU_INCLUDE_DIRS}
+ CMakeSourceDir.txt.in
+ "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt"
+ @ONLY
)
-# Check if we can build the Mach-O parser.
-if(CMake_USE_MACH_PARSER)
- set(MACH_SRCS cmMachO.h cmMachO.cxx)
-endif()
-
-# Check if we can build the XCOFF parser.
-if(CMake_USE_XCOFF_PARSER)
- set(XCOFF_SRCS cmXCOFF.h cmXCOFF.cxx)
-endif()
+# Add a dummy library and add sources later depends on condition
+add_library(ManifestLib INTERFACE)
#
-# Sources for CMakeLib
+# create a library used by the command line and the GUI
#
-set(SRCS
+add_library(
+ CMakeLib
# Lexers/Parsers
LexerParser/cmCommandArgumentLexer.cxx
LexerParser/cmCommandArgumentLexer.h
@@ -168,7 +146,9 @@ set(SRCS
cmCMakePresetsGraphReadJSON.cxx
cmCMakePresetsGraphReadJSONBuildPresets.cxx
cmCMakePresetsGraphReadJSONConfigurePresets.cxx
+ cmCMakePresetsGraphReadJSONPackagePresets.cxx
cmCMakePresetsGraphReadJSONTestPresets.cxx
+ cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
@@ -197,6 +177,8 @@ set(SRCS
cmCustomCommandLines.cxx
cmCustomCommandLines.h
cmCustomCommandTypes.h
+ cmCxxModuleMapper.cxx
+ cmCxxModuleMapper.h
cmDefinitions.cxx
cmDefinitions.h
cmDependencyProvider.h
@@ -367,7 +349,6 @@ set(SRCS
cmRulePlaceholderExpander.h
cmLocalUnixMakefileGenerator3.cxx
cmLocale.h
- ${MACH_SRCS}
cmMakefile.cxx
cmMakefile.h
cmMakefileTargetGenerator.cxx
@@ -467,7 +448,6 @@ set(SRCS
cmWorkerPool.h
cmWorkingDirectory.cxx
cmWorkingDirectory.h
- ${XCOFF_SRCS}
cmXMLParser.cxx
cmXMLParser.h
cmXMLSafe.cxx
@@ -543,6 +523,8 @@ set(SRCS
cmExecuteProcessCommand.h
cmExpandedCommandArgument.cxx
cmExpandedCommandArgument.h
+ cmExperimental.cxx
+ cmExperimental.h
cmExportCommand.cxx
cmExportCommand.h
cmExportLibraryDependenciesCommand.cxx
@@ -567,6 +549,8 @@ set(SRCS
cmFindProgramCommand.h
cmForEachCommand.cxx
cmForEachCommand.h
+ cmBlockCommand.cxx
+ cmBlockCommand.h
cmFunctionBlocker.cxx
cmFunctionBlocker.h
cmFunctionCommand.cxx
@@ -603,6 +587,8 @@ set(SRCS
cmInstallCommand.h
cmInstallCommandArguments.cxx
cmInstallCommandArguments.h
+ cmInstallCxxModuleBmiGenerator.cxx
+ cmInstallCxxModuleBmiGenerator.h
cmInstallFilesCommand.cxx
cmInstallFilesCommand.h
cmInstallProgramsCommand.cxx
@@ -721,6 +707,23 @@ set(SRCS
cmWhileCommand.h
cmWriteFileCommand.cxx
cmWriteFileCommand.h
+ # Ninja support
+ cmScanDepFormat.cxx
+ cmGlobalNinjaGenerator.cxx
+ cmGlobalNinjaGenerator.h
+ cmNinjaTypes.h
+ cmLocalNinjaGenerator.cxx
+ cmLocalNinjaGenerator.h
+ cmNinjaTargetGenerator.cxx
+ cmNinjaTargetGenerator.h
+ cmNinjaNormalTargetGenerator.cxx
+ cmNinjaNormalTargetGenerator.h
+ cmNinjaUtilityTargetGenerator.cxx
+ cmNinjaUtilityTargetGenerator.h
+ cmNinjaLinkLineComputer.cxx
+ cmNinjaLinkLineComputer.h
+ cmNinjaLinkLineDeviceComputer.cxx
+ cmNinjaLinkLineDeviceComputer.h
cm_get_date.h
cm_get_date.c
@@ -734,102 +737,152 @@ set(SRCS
bindexplib.cxx
)
+target_include_directories(
+ CMakeLib
+ PUBLIC
+ # add the include path to find the .h
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/LexerParser"
+ ${CMake_HAIKU_INCLUDE_DIRS}
+ )
+target_link_libraries(
+ CMakeLib
+ PUBLIC
+ cmstd
+ cmsys
+ CURL::libcurl
+ EXPAT::EXPAT
+ JsonCpp::JsonCpp
+ $<TARGET_NAME_IF_EXISTS:kwiml::kwiml>
+ LibArchive::LibArchive
+ LibRHash::LibRHash
+ LibUV::LibUV
+ Threads::Threads
+ ZLIB::ZLIB
+ )
-SET_PROPERTY(SOURCE cmProcessOutput.cxx cmWindowsRegistry.cxx APPEND PROPERTY COMPILE_DEFINITIONS
- KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
+# Check if we can build the Mach-O parser.
+if(CMake_USE_MACH_PARSER)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmMachO.h
+ cmMachO.cxx
+ )
+endif()
+
+# Check if we can build the XCOFF parser.
+if(CMake_USE_XCOFF_PARSER)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmXCOFF.h
+ cmXCOFF.cxx
+ )
+endif()
# Xcode only works on Apple
if(APPLE)
- set(SRCS ${SRCS}
- cmXCodeObject.cxx
- cmXCode21Object.cxx
- cmXCodeScheme.cxx
- cmGlobalXCodeGenerator.cxx
- cmGlobalXCodeGenerator.h
- cmLocalXCodeGenerator.cxx
- cmLocalXCodeGenerator.h)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmXCodeObject.cxx
+ cmXCode21Object.cxx
+ cmXCodeScheme.cxx
+ cmGlobalXCodeGenerator.cxx
+ cmGlobalXCodeGenerator.h
+ cmLocalXCodeGenerator.cxx
+ cmLocalXCodeGenerator.h
+ )
endif()
-
-if (WIN32)
- set(SRCS ${SRCS}
- cmCallVisualStudioMacro.cxx
- cmCallVisualStudioMacro.h
+if(WIN32)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmCallVisualStudioMacro.cxx
+ cmCallVisualStudioMacro.h
)
if(NOT UNIX)
- set(SRCS ${SRCS}
- cmGlobalBorlandMakefileGenerator.cxx
- cmGlobalBorlandMakefileGenerator.h
- cmGlobalMSYSMakefileGenerator.cxx
- cmGlobalMinGWMakefileGenerator.cxx
- cmGlobalNMakeMakefileGenerator.cxx
- cmGlobalNMakeMakefileGenerator.h
- cmGlobalJOMMakefileGenerator.cxx
- cmGlobalJOMMakefileGenerator.h
- cmGlobalVisualStudio71Generator.cxx
- cmGlobalVisualStudio71Generator.h
- cmGlobalVisualStudio7Generator.cxx
- cmGlobalVisualStudio7Generator.h
- cmGlobalVisualStudio8Generator.cxx
- cmGlobalVisualStudio8Generator.h
- cmGlobalVisualStudio9Generator.cxx
- cmGlobalVisualStudio9Generator.h
- cmVisualStudioGeneratorOptions.h
- cmVisualStudioGeneratorOptions.cxx
- cmVsProjectType.h
- cmVisualStudio10TargetGenerator.h
- cmVisualStudio10TargetGenerator.cxx
- cmLocalVisualStudio10Generator.cxx
- cmLocalVisualStudio10Generator.h
- cmGlobalVisualStudio10Generator.h
- cmGlobalVisualStudio10Generator.cxx
- cmGlobalVisualStudio11Generator.h
- cmGlobalVisualStudio11Generator.cxx
- cmGlobalVisualStudio12Generator.h
- cmGlobalVisualStudio12Generator.cxx
- cmGlobalVisualStudio14Generator.h
- cmGlobalVisualStudio14Generator.cxx
- cmGlobalVisualStudioGenerator.cxx
- cmGlobalVisualStudioGenerator.h
- cmGlobalVisualStudioVersionedGenerator.h
- cmGlobalVisualStudioVersionedGenerator.cxx
- cmIDEFlagTable.h
- cmIDEOptions.cxx
- cmIDEOptions.h
- cmLocalVisualStudio7Generator.cxx
- cmLocalVisualStudio7Generator.h
- cmLocalVisualStudioGenerator.cxx
- cmLocalVisualStudioGenerator.h
- cmVisualStudioSlnData.h
- cmVisualStudioSlnData.cxx
- cmVisualStudioSlnParser.h
- cmVisualStudioSlnParser.cxx
- cmVisualStudioWCEPlatformParser.h
- cmVisualStudioWCEPlatformParser.cxx
- cmVSSetupHelper.cxx
- cmVSSetupHelper.h
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmGlobalBorlandMakefileGenerator.cxx
+ cmGlobalBorlandMakefileGenerator.h
+ cmGlobalMSYSMakefileGenerator.cxx
+ cmGlobalMinGWMakefileGenerator.cxx
+ cmGlobalNMakeMakefileGenerator.cxx
+ cmGlobalNMakeMakefileGenerator.h
+ cmGlobalJOMMakefileGenerator.cxx
+ cmGlobalJOMMakefileGenerator.h
+ cmGlobalVisualStudio71Generator.cxx
+ cmGlobalVisualStudio71Generator.h
+ cmGlobalVisualStudio7Generator.cxx
+ cmGlobalVisualStudio7Generator.h
+ cmGlobalVisualStudio8Generator.cxx
+ cmGlobalVisualStudio8Generator.h
+ cmGlobalVisualStudio9Generator.cxx
+ cmGlobalVisualStudio9Generator.h
+ cmVisualStudioGeneratorOptions.h
+ cmVisualStudioGeneratorOptions.cxx
+ cmVsProjectType.h
+ cmVisualStudio10TargetGenerator.h
+ cmVisualStudio10TargetGenerator.cxx
+ cmLocalVisualStudio10Generator.cxx
+ cmLocalVisualStudio10Generator.h
+ cmGlobalVisualStudio10Generator.h
+ cmGlobalVisualStudio10Generator.cxx
+ cmGlobalVisualStudio11Generator.h
+ cmGlobalVisualStudio11Generator.cxx
+ cmGlobalVisualStudio12Generator.h
+ cmGlobalVisualStudio12Generator.cxx
+ cmGlobalVisualStudio14Generator.h
+ cmGlobalVisualStudio14Generator.cxx
+ cmGlobalVisualStudioGenerator.cxx
+ cmGlobalVisualStudioGenerator.h
+ cmGlobalVisualStudioVersionedGenerator.h
+ cmGlobalVisualStudioVersionedGenerator.cxx
+ cmIDEFlagTable.h
+ cmIDEOptions.cxx
+ cmIDEOptions.h
+ cmLocalVisualStudio7Generator.cxx
+ cmLocalVisualStudio7Generator.h
+ cmLocalVisualStudioGenerator.cxx
+ cmLocalVisualStudioGenerator.h
+ cmVisualStudioSlnData.h
+ cmVisualStudioSlnData.cxx
+ cmVisualStudioSlnParser.h
+ cmVisualStudioSlnParser.cxx
+ cmVisualStudioWCEPlatformParser.h
+ cmVisualStudioWCEPlatformParser.cxx
+ cmVSSetupHelper.cxx
+ cmVSSetupHelper.h
)
# Add a manifest file to executables on Windows to allow for
# GetVersion to work properly on Windows 8 and above.
- set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake.version.manifest)
+ target_sources(ManifestLib INTERFACE cmake.version.manifest)
endif()
-endif ()
+endif()
# Watcom support
-if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE)
- list(APPEND SRCS
- cmGlobalWatcomWMakeGenerator.cxx
- cmGlobalWatcomWMakeGenerator.h
+if(CMAKE_USE_WMAKE)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmGlobalWatcomWMakeGenerator.cxx
+ cmGlobalWatcomWMakeGenerator.h
)
endif()
# GHS support
# Works only for windows and linux
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
- set(SRCS ${SRCS}
+ target_sources(
+ CMakeLib
+ PRIVATE
cmGlobalGhsMultiGenerator.cxx
cmGlobalGhsMultiGenerator.h
cmLocalGhsMultiGenerator.cxx
@@ -841,104 +894,45 @@ if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
)
endif()
-
-# Ninja support
-set(SRCS ${SRCS}
- cmScanDepFormat.cxx
- cmGlobalNinjaGenerator.cxx
- cmGlobalNinjaGenerator.h
- cmNinjaTypes.h
- cmLocalNinjaGenerator.cxx
- cmLocalNinjaGenerator.h
- cmNinjaTargetGenerator.cxx
- cmNinjaTargetGenerator.h
- cmNinjaNormalTargetGenerator.cxx
- cmNinjaNormalTargetGenerator.h
- cmNinjaUtilityTargetGenerator.cxx
- cmNinjaUtilityTargetGenerator.h
- cmNinjaLinkLineComputer.cxx
- cmNinjaLinkLineComputer.h
- cmNinjaLinkLineDeviceComputer.cxx
- cmNinjaLinkLineDeviceComputer.h
- )
-
# Temporary variable for tools targets
set(_tools)
if(WIN32 AND NOT CYGWIN)
set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501)
- add_executable(cmcldeps cmcldeps.cxx ${MANIFEST_FILE})
+ add_executable(cmcldeps cmcldeps.cxx)
+ target_link_libraries(cmcldeps PRIVATE CMakeLib ManifestLib)
list(APPEND _tools cmcldeps)
- target_link_libraries(cmcldeps CMakeLib)
endif()
-foreach(v CURL_CA_BUNDLE CURL_CA_PATH)
- if(${v})
- set_property(SOURCE cmCurl.cxx APPEND PROPERTY COMPILE_DEFINITIONS ${v}="${${v}}")
- endif()
-endforeach()
-
-foreach(check
- STAT_HAS_ST_MTIM
- STAT_HAS_ST_MTIMESPEC
- )
- if(KWSYS_CXX_${check}_COMPILED) # abuse KWSys check cache entry
- set(CMake_${check} 1)
- else()
- set(CMake_${check} 0)
- endif()
- set_property(SOURCE cmFileTime.cxx APPEND PROPERTY
- COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}})
-endforeach()
-
-# create a library used by the command line and the GUI
-add_library(CMakeLib ${SRCS})
-target_link_libraries(CMakeLib cmsys
- ${CMAKE_STD_LIBRARY}
- ${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
- ${CMAKE_TAR_LIBRARIES}
- ${CMAKE_CURL_LIBRARIES}
- ${CMAKE_JSONCPP_LIBRARIES}
- ${CMAKE_LIBUV_LIBRARIES}
- ${CMAKE_LIBRHASH_LIBRARIES}
- ${CMake_KWIML_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- )
-
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
# the atomic instructions are implemented using libatomic on some platforms,
# so linking to that may be required
check_library_exists(atomic __atomic_fetch_add_4 "" LIBATOMIC_NEEDED)
if(LIBATOMIC_NEEDED)
- target_link_libraries(CMakeLib atomic)
+ target_link_libraries(CMakeLib PUBLIC atomic)
endif()
endif()
# On Apple we need CoreFoundation and CoreServices
if(APPLE)
- target_link_libraries(CMakeLib "-framework CoreFoundation")
- target_link_libraries(CMakeLib "-framework CoreServices")
+ target_link_libraries(CMakeLib PUBLIC "-framework CoreFoundation")
+ target_link_libraries(CMakeLib PUBLIC "-framework CoreServices")
endif()
if(WIN32 AND NOT UNIX)
# We need the rpcrt4 library on Windows.
# We need the crypt32 library on Windows for crypto/cert APIs.
- target_link_libraries(CMakeLib rpcrt4 crypt32)
+ target_link_libraries(CMakeLib PUBLIC rpcrt4 crypt32)
endif()
target_compile_definitions(CMakeLib PUBLIC ${CLANG_TIDY_DEFINITIONS})
#
-# CTestLib
-#
-include_directories(
- "${CMake_SOURCE_DIR}/Source/CTest"
- ${CMAKE_CURL_INCLUDES}
- )
-#
-# Sources for CTestLib
+# Build CTestLib
#
-set(CTEST_SRCS cmCTest.cxx
+add_library(
+ CTestLib
+ cmCTest.cxx
CTest/cmProcess.cxx
CTest/cmCTestBinPacker.cxx
CTest/cmCTestBuildAndTestHandler.cxx
@@ -1005,21 +999,18 @@ set(CTEST_SRCS cmCTest.cxx
LexerParser/cmCTestResourceGroupsLexer.h
LexerParser/cmCTestResourceGroupsLexer.in.l
)
-
-# Build CTestLib
-add_library(CTestLib ${CTEST_SRCS})
-target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES})
-
-#
-# CPack
-#
-include_directories(
- "${CMake_SOURCE_DIR}/Source/CPack"
+target_include_directories(
+ CTestLib
+ PUBLIC
+ "${CMAKE_CURRENT_SOURCE_DIR}/CTest"
)
+target_link_libraries(CTestLib PUBLIC CMakeLib)
+
#
-# Sources for CPack
+# Build CPackLib
#
-set(CPACK_SRCS
+add_library(
+ CPackLib
CPack/cmCPackArchiveGenerator.cxx
CPack/cmCPackComponentGroup.cxx
CPack/cmCPackDebGenerator.cxx
@@ -1030,9 +1021,7 @@ set(CPACK_SRCS
CPack/cmCPackNSISGenerator.cxx
CPack/cmCPackNuGetGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
- )
-# CPack IFW generator
-set(CPACK_SRCS ${CPACK_SRCS}
+ # CPack IFW generator
CPack/IFW/cmCPackIFWCommon.cxx
CPack/IFW/cmCPackIFWCommon.h
CPack/IFW/cmCPackIFWGenerator.cxx
@@ -1044,19 +1033,20 @@ set(CPACK_SRCS ${CPACK_SRCS}
CPack/IFW/cmCPackIFWRepository.cxx
CPack/IFW/cmCPackIFWRepository.h
)
-
-if(CYGWIN)
- set(CPACK_SRCS ${CPACK_SRCS}
- CPack/cmCPackCygwinBinaryGenerator.cxx
- CPack/cmCPackCygwinSourceGenerator.cxx
- )
-endif()
+target_include_directories(
+ CPackLib
+ PUBLIC
+ "${CMAKE_CURRENT_SOURCE_DIR}/CPack"
+ "${CMAKE_CURRENT_BINARY_DIR}/CPack"
+ )
+target_link_libraries(CPackLib PUBLIC CMakeLib)
option(CPACK_ENABLE_FREEBSD_PKG "Add FreeBSD pkg(8) generator to CPack." OFF)
-
if(UNIX)
- set(CPACK_SRCS ${CPACK_SRCS}
- CPack/cmCPackRPMGenerator.cxx
+ target_sources(
+ CPackLib
+ PRIVATE
+ CPack/cmCPackRPMGenerator.cxx
)
# Optionally, try to use pkg(8)
@@ -1072,13 +1062,14 @@ if(UNIX)
pkg
DOC "FreeBSD pkg(8) library")
if(FREEBSD_PKG_LIBRARIES)
- set(CPACK_SRCS ${CPACK_SRCS}
- CPack/cmCPackFreeBSDGenerator.cxx
- )
+ set(ENABLE_BUILD_FREEBSD_PKG 1)
+ target_sources(CPackLib PRIVATE CPack/cmCPackFreeBSDGenerator.cxx)
+ target_include_directories(CPackLib PUBLIC ${FREEBSD_PKG_INCLUDE_DIRS})
+ target_link_libraries(CPackLib PUBLIC ${FREEBSD_PKG_LIBRARIES})
endif()
endif()
- if (NOT FREEBSD_PKG_INCLUDE_DIRS OR NOT FREEBSD_PKG_LIBRARIES)
+ if(NOT FREEBSD_PKG_INCLUDE_DIRS OR NOT FREEBSD_PKG_LIBRARIES)
message(FATAL_ERROR "CPack needs libpkg(3) to produce FreeBSD packages natively.")
endif()
else()
@@ -1088,47 +1079,57 @@ if(UNIX)
endif()
if(CYGWIN)
+ target_sources(
+ CPackLib
+ PRIVATE
+ CPack/cmCPackCygwinBinaryGenerator.cxx
+ CPack/cmCPackCygwinSourceGenerator.cxx
+ )
find_package(LibUUID)
endif()
-if(WIN32 OR (CYGWIN AND LibUUID_FOUND))
- set(CPACK_SRCS ${CPACK_SRCS}
- CPack/WiX/cmCMakeToWixPath.cxx
- CPack/WiX/cmCMakeToWixPath.h
- CPack/WiX/cmCPackWIXGenerator.cxx
- CPack/WiX/cmCPackWIXGenerator.h
- CPack/WiX/cmWIXAccessControlList.cxx
- CPack/WiX/cmWIXAccessControlList.h
- CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
- CPack/WiX/cmWIXDirectoriesSourceWriter.h
- CPack/WiX/cmWIXFeaturesSourceWriter.cxx
- CPack/WiX/cmWIXFeaturesSourceWriter.h
- CPack/WiX/cmWIXFilesSourceWriter.cxx
- CPack/WiX/cmWIXFilesSourceWriter.h
- CPack/WiX/cmWIXPatch.cxx
- CPack/WiX/cmWIXPatch.h
- CPack/WiX/cmWIXPatchParser.cxx
- CPack/WiX/cmWIXPatchParser.h
- CPack/WiX/cmWIXRichTextFormatWriter.cxx
- CPack/WiX/cmWIXRichTextFormatWriter.h
- CPack/WiX/cmWIXShortcut.cxx
- CPack/WiX/cmWIXShortcut.h
- CPack/WiX/cmWIXSourceWriter.cxx
- CPack/WiX/cmWIXSourceWriter.h
+
+if(WIN32 OR (CYGWIN AND TARGET LibUUID::LibUUID))
+ set(ENABLE_BUILD_WIX_GENERATOR 1)
+ target_sources(
+ CPackLib
+ PRIVATE
+ CPack/WiX/cmCMakeToWixPath.cxx
+ CPack/WiX/cmCMakeToWixPath.h
+ CPack/WiX/cmCPackWIXGenerator.cxx
+ CPack/WiX/cmCPackWIXGenerator.h
+ CPack/WiX/cmWIXAccessControlList.cxx
+ CPack/WiX/cmWIXAccessControlList.h
+ CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
+ CPack/WiX/cmWIXDirectoriesSourceWriter.h
+ CPack/WiX/cmWIXFeaturesSourceWriter.cxx
+ CPack/WiX/cmWIXFeaturesSourceWriter.h
+ CPack/WiX/cmWIXFilesSourceWriter.cxx
+ CPack/WiX/cmWIXFilesSourceWriter.h
+ CPack/WiX/cmWIXPatch.cxx
+ CPack/WiX/cmWIXPatch.h
+ CPack/WiX/cmWIXPatchParser.cxx
+ CPack/WiX/cmWIXPatchParser.h
+ CPack/WiX/cmWIXRichTextFormatWriter.cxx
+ CPack/WiX/cmWIXRichTextFormatWriter.h
+ CPack/WiX/cmWIXShortcut.cxx
+ CPack/WiX/cmWIXShortcut.h
+ CPack/WiX/cmWIXSourceWriter.cxx
+ CPack/WiX/cmWIXSourceWriter.h
)
+ target_link_libraries(CPackLib PUBLIC $<TARGET_NAME_IF_EXISTS:LibUUID::LibUUID>)
endif()
if(APPLE)
- set(CPACK_SRCS ${CPACK_SRCS}
- CPack/cmCPackBundleGenerator.cxx
- CPack/cmCPackDragNDropGenerator.cxx
- CPack/cmCPackPKGGenerator.cxx
- CPack/cmCPackProductBuildGenerator.cxx
+ target_sources(
+ CPackLib
+ PRIVATE
+ CPack/cmCPackBundleGenerator.cxx
+ CPack/cmCPackDragNDropGenerator.cxx
+ CPack/cmCPackPKGGenerator.cxx
+ CPack/cmCPackProductBuildGenerator.cxx
)
endif()
-# Build CPackLib
-add_library(CPackLib ${CPACK_SRCS})
-target_link_libraries(CPackLib CMakeLib)
if(APPLE)
# Some compilers produce errors in the CoreServices framework headers.
# Ideally such errors should be fixed by either the compiler vendor
@@ -1136,8 +1137,7 @@ if(APPLE)
# If it does not work, build with reduced functionality and warn.
check_include_file("CoreServices/CoreServices.h" HAVE_CoreServices)
if(HAVE_CoreServices)
- set_property(SOURCE CPack/cmCPackDragNDropGenerator.cxx PROPERTY COMPILE_DEFINITIONS HAVE_CoreServices)
- target_link_libraries(CPackLib "-framework CoreServices")
+ target_link_libraries(CPackLib PUBLIC "-framework CoreServices")
else()
message(WARNING "This compiler does not appear to support\n"
" #include <CoreServices/CoreServices.h>\n"
@@ -1145,31 +1145,25 @@ if(APPLE)
"See CMakeFiles/CMakeError.log for details of the failure.")
endif()
endif()
-if(CYGWIN AND LibUUID_FOUND)
- target_link_libraries(CPackLib ${LibUUID_LIBRARIES})
- include_directories(CPackLib ${LibUUID_INCLUDE_DIRS})
- set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID)
-endif()
-if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES)
- target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES})
- include_directories(${FREEBSD_PKG_INCLUDE_DIRS})
- add_definitions(-DHAVE_FREEBSD_PKG)
-endif()
+
+# Render config header file for CPackLib
+configure_file(CPack/cmCPackConfigure.h.in CPack/cmCPackConfigure.h)
+
# Build CMake executable
-add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE})
+add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h)
+target_link_libraries(cmake PRIVATE CMakeLib ManifestLib)
list(APPEND _tools cmake)
-target_link_libraries(cmake CMakeLib)
# Build CTest executable
-add_executable(ctest ctest.cxx ${MANIFEST_FILE})
+add_executable(ctest ctest.cxx)
+target_link_libraries(ctest PRIVATE CTestLib ManifestLib)
list(APPEND _tools ctest)
-target_link_libraries(ctest CTestLib)
# Build CPack executable
-add_executable(cpack CPack/cpack.cxx ${MANIFEST_FILE})
+add_executable(cpack CPack/cpack.cxx)
+target_link_libraries(cpack PRIVATE CPackLib ManifestLib)
list(APPEND _tools cpack)
-target_link_libraries(cpack CPackLib)
# Curses GUI
if(BUILD_CursesDialog)
@@ -1182,8 +1176,8 @@ if(BUILD_QtDialog)
add_subdirectory(QtDialog)
endif()
-include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
-include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
+include(${CMAKE_CURRENT_BINARY_DIR}/LocalUserOptions.cmake OPTIONAL)
+include(${CMAKE_CURRENT_SOURCE_DIR}/LocalUserOptions.cmake OPTIONAL)
if(WIN32)
# Compute the binary version that appears in the RC file. Version
@@ -1202,14 +1196,14 @@ if(WIN32)
set(CMake_RCVERSION_STR ${CMake_VERSION})
# Add Windows executable version information.
- configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY)
+ configure_file(CMakeVersion.rc.in CMakeVersion.rc @ONLY)
# We use a separate object library for this to work around a limitation of
# MinGW's windres tool with spaces in the path to the include directories.
add_library(CMakeVersion OBJECT "${CMAKE_CURRENT_BINARY_DIR}/CMakeVersion.rc")
set_property(TARGET CMakeVersion PROPERTY INCLUDE_DIRECTORIES "")
- foreach(_tool ${_tools})
- target_sources(${_tool} PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
+ foreach(_tool IN LISTS _tools)
+ target_link_libraries(${_tool} PRIVATE CMakeVersion)
endforeach()
endif()
@@ -1220,7 +1214,7 @@ endif()
# Install tools
-foreach(_tool ${_tools})
+foreach(_tool IN LISTS _tools)
CMake_OPTIONAL_COMPONENT(${_tool})
install(TARGETS ${_tool} DESTINATION ${CMAKE_BIN_DIR} ${COMPONENT})
endforeach()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index be3ae8f72..e4575f40c 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 24)
-set(CMake_VERSION_PATCH 3)
+set(CMake_VERSION_MINOR 25)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
@@ -9,7 +9,7 @@ set(CMake_VERSION_IS_DIRTY 0)
set(CMake_VERSION
"${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}")
if(DEFINED CMake_VERSION_RC)
- set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}")
+ string(APPEND CMake_VERSION "-rc${CMake_VERSION_RC}")
endif()
# Releases define a small patch level.
@@ -21,7 +21,7 @@ endif()
if(NOT CMake_VERSION_NO_GIT)
# If this source was exported by 'git archive', use its commit info.
- set(git_info [==[c974557598 CMake 3.24.3]==])
+ set(git_info [==[13e46189c7 CMake 3.25.0]==])
# Otherwise, try to identify the current development source version.
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
@@ -53,7 +53,7 @@ if(NOT CMake_VERSION_NO_GIT)
# If this is not the exact commit of a release, add dev info.
if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$")
- set(CMake_VERSION "${CMake_VERSION}-g${git_hash}")
+ string(APPEND CMake_VERSION "-g${git_hash}")
endif()
# If this is a work tree, check whether it is dirty.
@@ -68,7 +68,7 @@ if(NOT CMake_VERSION_NO_GIT)
# No commit information.
if(NOT CMake_VERSION_IS_RELEASE)
# Generic development version.
- set(CMake_VERSION "${CMake_VERSION}-git")
+ string(APPEND CMake_VERSION "-git")
endif()
endif()
endif()
@@ -80,5 +80,5 @@ else()
set(CMake_VERSION_SUFFIX "")
endif()
if(CMake_VERSION_IS_DIRTY)
- set(CMake_VERSION ${CMake_VERSION}-dirty)
+ string(APPEND CMake_VERSION "-dirty")
endif()
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 56e8463c1..894c24bce 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -94,6 +94,18 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
int cmCPackArchiveGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
+ cmValue newExtensionValue = this->GetOption("CPACK_ARCHIVE_FILE_EXTENSION");
+ if (!newExtensionValue.IsEmpty()) {
+ std::string newExtension = *newExtensionValue;
+ if (!cmHasLiteralPrefix(newExtension, ".")) {
+ newExtension = cmStrCat('.', newExtension);
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Using user-provided file extension "
+ << newExtension << " instead of the default "
+ << this->OutputExtension << std::endl);
+ this->OutputExtension = std::move(newExtension);
+ }
return this->Superclass::InitializeInternal();
}
diff --git a/Source/CPack/cmCPackConfigure.h.in b/Source/CPack/cmCPackConfigure.h.in
index 8ac1661ec..2c1302dbf 100644
--- a/Source/CPack/cmCPackConfigure.h.in
+++ b/Source/CPack/cmCPackConfigure.h.in
@@ -1,2 +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
+
+#cmakedefine01 ENABLE_BUILD_WIX_GENERATOR
+#cmakedefine01 ENABLE_BUILD_FREEBSD_PKG
+#cmakedefine01 HAVE_CoreServices
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 0f7acfb55..057906610 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
+#include "cmCPackConfigure.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmDuration.h"
@@ -23,7 +24,7 @@
#include "cmValue.h"
#include "cmXMLWriter.h"
-#ifdef HAVE_CoreServices
+#if HAVE_CoreServices
// For the old LocaleStringToLangAndRegionCodes() function, to convert
// to the old Script Manager RegionCode values needed for the 'LPic' data
// structure used for generating multi-lingual SLAs.
@@ -590,7 +591,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
kCFStringEncodingMacRoman);
LangCode lang = 0;
RegionCode region = 0;
-#ifdef HAVE_CoreServices
+#if HAVE_CoreServices
OSStatus err =
LocaleStringToLangAndRegionCodes(iso_language_cstr, &lang, &region);
if (err != noErr)
@@ -601,7 +602,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
<< iso_language_cstr << std::endl);
return 0;
}
-#ifdef HAVE_CoreServices
+#if HAVE_CoreServices
header_data.push_back(region);
header_data.push_back(i);
header_data.push_back(0);
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index 607d79772..162dfc734 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -23,8 +23,6 @@
// Suffix used to tell libpkg what compression to use
static const char FreeBSDPackageCompression[] = "txz";
-// Resulting package file-suffix, for < 1.17 and >= 1.17 versions of libpkg
-static const char FreeBSDPackageSuffix_10[] = ".txz";
static const char FreeBSDPackageSuffix_17[] = ".pkg";
cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator()
@@ -83,6 +81,14 @@ public:
{
if (!isValid())
return false;
+ // The API in the FreeBSD sources (the header has no documentation),
+ // is as follows:
+ //
+ // int pkg_create(struct pkg_create *pc, const char *metadata, const char
+ // *plist, bool hash)
+ //
+ // We let the plist be determined from what is installed, and all
+ // the rest comes from the manifest data.
int r = pkg_create(d, manifest.c_str(), nullptr, false);
return r == 0;
}
@@ -402,7 +408,8 @@ int cmCPackFreeBSDGenerator::PackageFiles()
return 0;
}
- std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel);
+ const std::string output_dir =
+ cmSystemTools::CollapseFullPath("../", toplevel);
PkgCreate package(output_dir, toplevel, manifestname);
if (package.isValid()) {
if (!package.Create()) {
@@ -416,40 +423,33 @@ int cmCPackFreeBSDGenerator::PackageFiles()
return 0;
}
- // Specifically looking for packages suffixed with the TAG, either extension
- std::string broken_suffix_10 =
- cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_10);
+ // Specifically looking for packages suffixed with the TAG
std::string broken_suffix_17 =
cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_17);
for (std::string& name : packageFileNames) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl);
- if (cmHasSuffix(name, broken_suffix_10)) {
- name.replace(name.size() - broken_suffix_10.size(), std::string::npos,
- FreeBSDPackageSuffix_10);
- break;
- }
if (cmHasSuffix(name, broken_suffix_17)) {
name.replace(name.size() - broken_suffix_17.size(), std::string::npos,
FreeBSDPackageSuffix_17);
break;
}
}
- // If the name uses a *new* style name, which doesn't exist, but there
- // is an *old* style name, then use that instead. This indicates we used
- // an older libpkg, which still creates .txz instead of .pkg files.
- for (std::string& name : packageFileNames) {
- if (cmHasSuffix(name, FreeBSDPackageSuffix_17) &&
- !cmSystemTools::FileExists(name)) {
- const std::string badSuffix(FreeBSDPackageSuffix_17);
- const std::string goodSuffix(FreeBSDPackageSuffix_10);
- std::string repairedName(name);
- repairedName.replace(repairedName.size() - badSuffix.size(),
- std::string::npos, goodSuffix);
- if (cmSystemTools::FileExists(repairedName)) {
- name = repairedName;
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Repaired packagefile " << name << std::endl);
- }
+
+ const std::string packageFileName =
+ var_lookup("CPACK_PACKAGE_FILE_NAME") + FreeBSDPackageSuffix_17;
+ if (packageFileNames.size() == 1 && !packageFileName.empty() &&
+ packageFileNames[0] != packageFileName) {
+ // Since libpkg always writes <name>-<version>.<suffix>,
+ // if there is a CPACK_PACKAGE_FILE_NAME set, we need to
+ // rename, and then re-set the name.
+ const std::string sourceFile = packageFileNames[0];
+ const std::string packageSubDirectory =
+ cmSystemTools::GetParentDirectory(sourceFile);
+ const std::string targetFileName =
+ packageSubDirectory + '/' + packageFileName;
+ if (cmSystemTools::RenameFile(sourceFile, targetFileName)) {
+ this->packageFileNames.clear();
+ this->packageFileNames.emplace_back(targetFileName);
}
}
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 725ea8a73..efb94b9d8 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -6,7 +6,7 @@
#include <utility>
#include "IFW/cmCPackIFWGenerator.h"
-#ifdef HAVE_FREEBSD_PKG
+#if ENABLE_BUILD_FREEBSD_PKG
# include "cmCPackFreeBSDGenerator.h"
#endif
#include "cmCPackArchiveGenerator.h"
@@ -34,7 +34,7 @@
# include "cmCPackRPMGenerator.h"
#endif
-#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
+#if ENABLE_BUILD_WIX_GENERATOR
# include "WiX/cmCPackWIXGenerator.h"
#endif
@@ -80,7 +80,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
cmCPackCygwinSourceGenerator::CreateGenerator);
}
#endif
-#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
+#if ENABLE_BUILD_WIX_GENERATOR
if (cmCPackWIXGenerator::CanGenerate()) {
this->RegisterGenerator("WIX", "MSI file format via WiX tools",
cmCPackWIXGenerator::CreateGenerator);
@@ -119,7 +119,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
cmCPackRPMGenerator::CreateGenerator);
}
#endif
-#ifdef HAVE_FREEBSD_PKG
+#if ENABLE_BUILD_FREEBSD_PKG
if (cmCPackFreeBSDGenerator::CanGenerate()) {
this->RegisterGenerator("FREEBSD", "FreeBSD pkg(8) packages",
cmCPackFreeBSDGenerator::CreateGenerator);
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index f3e25a65d..52c1b5cc8 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -8,6 +8,8 @@
#include <memory>
#include <string>
+#include "cmCPackConfigure.h" // IWYU pragma: keep
+
class cmCPackGenerator;
class cmCPackLog;
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 217f716ea..6ca57830a 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -242,6 +242,33 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode);
}
+ std::string nsisPreArguments;
+ if (cmValue nsisArguments =
+ this->GetOption("CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS")) {
+ std::vector<std::string> expandedArguments;
+ cmExpandList(nsisArguments, expandedArguments);
+
+ for (auto& arg : expandedArguments) {
+ if (!cmHasPrefix(arg, NSIS_OPT)) {
+ nsisPreArguments = cmStrCat(nsisPreArguments, NSIS_OPT);
+ }
+ nsisPreArguments = cmStrCat(nsisPreArguments, arg, ' ');
+ }
+ }
+
+ std::string nsisPostArguments;
+ if (cmValue nsisArguments =
+ this->GetOption("CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS")) {
+ std::vector<std::string> expandedArguments;
+ cmExpandList(nsisArguments, expandedArguments);
+ for (auto& arg : expandedArguments) {
+ if (!cmHasPrefix(arg, NSIS_OPT)) {
+ nsisPostArguments = cmStrCat(nsisPostArguments, NSIS_OPT);
+ }
+ nsisPostArguments = cmStrCat(nsisPostArguments, arg, ' ');
+ }
+ }
+
// Setup all of the component sections
if (this->Components.empty()) {
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", "");
@@ -358,8 +385,11 @@ int cmCPackNSISGenerator::PackageFiles()
this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions);
this->ConfigureFile(nsisInFileName, nsisFileName);
std::string nsisCmd =
- cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"",
- nsisFileName, '"');
+ cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" ",
+ nsisPreArguments, " \"", nsisFileName, '"');
+ if (!nsisPostArguments.empty()) {
+ nsisCmd = cmStrCat(nsisCmd, " ", nsisPostArguments);
+ }
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 165036843..f06946bea 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -1,6 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
@@ -11,10 +12,12 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cmext/algorithm>
#include "cmsys/Encoding.hxx"
+#include "cmCMakePresetsGraph.h"
#include "cmCPackGenerator.h"
#include "cmCPackGeneratorFactory.h"
#include "cmCPackLog.h"
@@ -50,7 +53,7 @@ const char* cmDocumentationOptions[][2] = {
{ "-C <Configuration>", "Specify the project configuration" },
{ "-D <var>=<value>", "Set a CPack variable." },
{ "--config <configFile>", "Specify the config file." },
- { "--verbose,-V", "Enable verbose output" },
+ { "-V,--verbose", "Enable verbose output" },
{ "--trace", "Put underlying cmake scripts in trace mode." },
{ "--trace-expand", "Put underlying cmake scripts in expanded trace mode." },
{ "--debug", "Enable debug output (for CPack developers)" },
@@ -58,6 +61,8 @@ const char* cmDocumentationOptions[][2] = {
{ "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" },
{ "-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 }
};
@@ -116,6 +121,9 @@ int main(int argc, char const* const* argv)
std::string cpackProjectVendor;
std::string cpackConfigFile;
+ std::string preset;
+ bool listPresets = false;
+
std::map<std::string, std::string> definitions;
auto const verboseLambda = [&log](const std::string&, cmake*,
@@ -182,6 +190,10 @@ int main(int argc, char const* const* argv)
CommandArgument::setToValue(cpackProjectPatch) },
CommandArgument{ "--vendor", CommandArgument::Values::One,
CommandArgument::setToValue(cpackProjectVendor) },
+ CommandArgument{ "--preset", CommandArgument::Values::One,
+ CommandArgument::setToValue(preset) },
+ CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
+ CommandArgument::setToTrue(listPresets) },
CommandArgument{
"-D", CommandArgument::Values::One,
[&log, &definitions](const std::string& arg, cmake*,
@@ -228,6 +240,160 @@ int main(int argc, char const* const* argv)
}
}
+ cmCPackGeneratorFactory generators;
+ generators.SetLogger(&log);
+
+ // Set up presets
+ if (!preset.empty() || listPresets) {
+ const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+
+ auto const presetGeneratorsPresent =
+ [&generators](const cmCMakePresetsGraph::PackagePreset& p) {
+ return std::all_of(p.Generators.begin(), p.Generators.end(),
+ [&generators](const std::string& gen) {
+ return generators.GetGeneratorsList().count(
+ gen) != 0;
+ });
+ };
+
+ cmCMakePresetsGraph presetsGraph;
+ auto result = presetsGraph.ReadProjectPresets(workingDirectory);
+ if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Could not read presets from "
+ << workingDirectory << ": "
+ << cmCMakePresetsGraph::ResultToString(result)
+ << std::endl);
+ return 1;
+ }
+
+ if (listPresets) {
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 0;
+ }
+
+ auto presetPair = presetsGraph.PackagePresets.find(preset);
+ if (presetPair == presetsGraph.PackagePresets.end()) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "No such package preset in " << workingDirectory << ": \""
+ << preset << '"' << std::endl);
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 1;
+ }
+
+ if (presetPair->second.Unexpanded.Hidden) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Cannot use hidden package preset in "
+ << workingDirectory << ": \"" << preset << '"'
+ << std::endl);
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 1;
+ }
+
+ auto const& expandedPreset = presetPair->second.Expanded;
+ if (!expandedPreset) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Could not evaluate package preset \""
+ << preset << "\": Invalid macro expansion" << std::endl);
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 1;
+ }
+
+ if (!expandedPreset->ConditionResult) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Cannot use disabled package preset in "
+ << workingDirectory << ": \"" << preset << '"'
+ << std::endl);
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 1;
+ }
+
+ if (!presetGeneratorsPresent(presetPair->second.Unexpanded)) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use preset");
+ presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
+ return 1;
+ }
+
+ auto configurePresetPair =
+ presetsGraph.ConfigurePresets.find(expandedPreset->ConfigurePreset);
+ if (configurePresetPair == presetsGraph.ConfigurePresets.end()) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "No such configure preset in "
+ << workingDirectory << ": \""
+ << expandedPreset->ConfigurePreset << '"' << std::endl);
+ presetsGraph.PrintConfigurePresetList();
+ return 1;
+ }
+
+ if (configurePresetPair->second.Unexpanded.Hidden) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Cannot use hidden configure preset in "
+ << workingDirectory << ": \""
+ << expandedPreset->ConfigurePreset << '"' << std::endl);
+ presetsGraph.PrintConfigurePresetList();
+ return 1;
+ }
+
+ auto const& expandedConfigurePreset = configurePresetPair->second.Expanded;
+ if (!expandedConfigurePreset) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "Could not evaluate configure preset \""
+ << expandedPreset->ConfigurePreset
+ << "\": Invalid macro expansion" << std::endl);
+ return 1;
+ }
+
+ cmSystemTools::ChangeDirectory(expandedConfigurePreset->BinaryDir);
+
+ auto presetEnvironment = expandedPreset->Environment;
+ for (auto const& var : presetEnvironment) {
+ if (var.second) {
+ cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second));
+ }
+ }
+
+ if (!expandedPreset->ConfigFile.empty() && cpackConfigFile.empty()) {
+ cpackConfigFile = expandedPreset->ConfigFile;
+ }
+
+ if (!expandedPreset->Generators.empty() && generator.empty()) {
+ generator = cmJoin(expandedPreset->Generators, ";");
+ }
+
+ if (!expandedPreset->Configurations.empty() && cpackBuildConfig.empty()) {
+ cpackBuildConfig = cmJoin(expandedPreset->Configurations, ";");
+ }
+
+ definitions.insert(expandedPreset->Variables.begin(),
+ expandedPreset->Variables.end());
+
+ if (expandedPreset->DebugOutput == true) {
+ debugLambda("", &cminst, &globalMF);
+ }
+
+ if (expandedPreset->VerboseOutput == true) {
+ verboseLambda("", &cminst, &globalMF);
+ }
+
+ if (!expandedPreset->PackageName.empty() && cpackProjectName.empty()) {
+ cpackProjectName = expandedPreset->PackageName;
+ }
+
+ if (!expandedPreset->PackageVersion.empty() &&
+ cpackProjectVersion.empty()) {
+ cpackProjectVersion = expandedPreset->PackageVersion;
+ }
+
+ if (!expandedPreset->PackageDirectory.empty() &&
+ cpackProjectDirectory.empty()) {
+ cpackProjectDirectory = expandedPreset->PackageDirectory;
+ }
+
+ if (!expandedPreset->VendorName.empty() && cpackProjectVendor.empty()) {
+ cpackProjectVendor = expandedPreset->VendorName;
+ }
+ }
+
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Read CPack config file: " << cpackConfigFile << std::endl);
@@ -238,9 +404,6 @@ int main(int argc, char const* const* argv)
cpackConfigFileSpecified = false;
}
- cmCPackGeneratorFactory generators;
- generators.SetLogger(&log);
-
cmDocumentation doc;
doc.addCPackStandardDocSections();
/* Were we invoked to display doc or to do some work ?
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 7432d0850..97b0a8994 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -4,7 +4,6 @@
#include <set>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -18,13 +17,6 @@ void cmCTestCoverageCommand::BindArguments()
this->Bind("LABELS"_s, this->Labels);
}
-void cmCTestCoverageCommand::CheckArguments(
- std::vector<std::string> const& keywords)
-{
- this->LabelsMentioned =
- !this->Labels.empty() || cm::contains(keywords, "LABELS");
-}
-
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
{
this->CTest->SetCTestConfigurationFromCMakeVariable(
@@ -36,9 +28,9 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
handler->Initialize();
// If a LABELS option was given, select only files with the labels.
- if (this->LabelsMentioned) {
+ if (this->Labels) {
handler->SetLabelFilter(
- std::set<std::string>(this->Labels.begin(), this->Labels.end()));
+ std::set<std::string>(this->Labels->begin(), this->Labels->end()));
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 93448529a..55c68b201 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -9,7 +9,9 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
+#include "cmArgumentParserTypes.h" // IWYU pragma: keep
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -41,9 +43,7 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool LabelsMentioned;
- std::vector<std::string> Labels;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Labels;
};
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5494d20da..be952cd26 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -7,6 +7,7 @@
#include <cstring>
#include <sstream>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -81,15 +82,13 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// Process input arguments.
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- this->Parse(args, &unparsedArguments, &keywordsMissingValue,
- &parsedKeywords);
- this->CheckArguments(keywordsMissingValue);
-
- std::sort(parsedKeywords.begin(), parsedKeywords.end());
- auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
- if (it != parsedKeywords.end()) {
+ this->Parse(args, &unparsedArguments);
+ this->CheckArguments();
+
+ std::sort(this->ParsedKeywords.begin(), this->ParsedKeywords.end());
+ auto it = std::adjacent_find(this->ParsedKeywords.begin(),
+ this->ParsedKeywords.end());
+ if (it != this->ParsedKeywords.end()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Called with more than one value for ", *it));
@@ -233,6 +232,7 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
void cmCTestHandlerCommand::BindArguments()
{
+ this->BindParsedKeywords(this->ParsedKeywords);
this->Bind("APPEND"_s, this->Append);
this->Bind("QUIET"_s, this->Quiet);
this->Bind("RETURN_VALUE"_s, this->ReturnValue);
@@ -242,6 +242,6 @@ void cmCTestHandlerCommand::BindArguments()
this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestHandlerCommand::CheckArguments()
{
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 756952d8e..ed6d9af58 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -7,6 +7,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmArgumentParser.h"
#include "cmCTestCommand.h"
@@ -42,8 +44,9 @@ protected:
// Command argument handling.
virtual void BindArguments();
- virtual void CheckArguments(std::vector<std::string> const& keywords);
+ virtual void CheckArguments();
+ std::vector<cm::string_view> ParsedKeywords;
bool Append = false;
bool Quiet = false;
std::string CaptureCMakeError;
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 788845b3e..6f6a6426a 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -1177,6 +1177,13 @@ bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput(
// generic error: ignore ERROR SUMMARY, CUDA-MEMCHECK and others
"== ([A-Z][a-z].*)"
};
+ // matchers for messages that aren't defects, but caught by above matchers
+ std::vector<cmsys::RegularExpression> false_positive_matchers{
+ "== Error: No attachable process found.*timed-out",
+ "== Default timeout can be adjusted with --launch-timeout",
+ "== Error: Target application terminated before first instrumented API",
+ "== Tracking kernels launched by child processes requires"
+ };
std::vector<std::string::size_type> nonMemcheckOutput;
auto sttime = std::chrono::steady_clock::now();
@@ -1196,11 +1203,17 @@ bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput(
if (leakExpr.find(line)) {
failure = static_cast<int>(this->FindOrAddWarning("Memory leak"));
} else {
- for (auto& matcher : matchers) {
- if (matcher.find(line)) {
+ auto match_predicate =
+ [&line](cmsys::RegularExpression& matcher) -> bool {
+ return matcher.find(line);
+ };
+ auto const pos_matcher =
+ std::find_if(matchers.begin(), matchers.end(), match_predicate);
+ if (pos_matcher != matchers.end()) {
+ if (!std::any_of(false_positive_matchers.begin(),
+ false_positive_matchers.end(), match_predicate)) {
failure =
- static_cast<int>(this->FindOrAddWarning(matcher.match(1)));
- break;
+ static_cast<int>(this->FindOrAddWarning(pos_matcher->match(1)));
}
}
}
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 2a2cb1cbf..5efe69f52 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -8,16 +8,12 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
-#include <functional>
#include <iomanip>
#include <ratio>
#include <sstream>
#include <utility>
#include <cm/memory>
-#include <cm/optional>
-#include <cm/string_view>
-#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -787,149 +783,31 @@ bool cmCTestRunTest::ForkProcess(
this->TestProcess->SetTimeout(timeout);
-#ifndef CMAKE_BOOTSTRAP
cmSystemTools::SaveRestoreEnvironment sre;
-#endif
-
std::ostringstream envMeasurement;
+
+ // We split processing ENVIRONMENT and ENVIRONMENT_MODIFICATION into two
+ // phases to ensure that MYVAR=reset: in the latter phase resets to the
+ // former phase's settings, rather than to the original environment.
if (environment && !environment->empty()) {
- // Environment modification works on the assumption that the environment is
- // actually modified here. If another strategy is used, there will need to
- // be updates below in `apply_diff`.
- cmSystemTools::AppendEnv(*environment);
- for (auto const& var : *environment) {
- envMeasurement << var << std::endl;
- }
+ cmSystemTools::EnvDiff diff;
+ diff.AppendEnv(*environment);
+ diff.ApplyToCurrentEnv(&envMeasurement);
}
if (environment_modification && !environment_modification->empty()) {
- std::map<std::string, cm::optional<std::string>> env_application;
-
-#ifdef _WIN32
- char path_sep = ';';
-#else
- char path_sep = ':';
-#endif
-
- auto apply_diff =
- [&env_application](const std::string& name,
- std::function<void(std::string&)> const& apply) {
- cm::optional<std::string> old_value = env_application[name];
- std::string output;
- if (old_value) {
- output = *old_value;
- } else {
- // This only works because the environment is actually modified above
- // (`AppendEnv`). If CTest ever just creates an environment block
- // directly, that block will need to be queried for the subprocess'
- // value instead.
- const char* curval = cmSystemTools::GetEnv(name);
- if (curval) {
- output = curval;
- }
- }
- apply(output);
- env_application[name] = output;
- };
-
- bool err_occurred = false;
+ cmSystemTools::EnvDiff diff;
+ bool env_ok = true;
for (auto const& envmod : *environment_modification) {
- // Split on `=`
- auto const eq_loc = envmod.find_first_of('=');
- if (eq_loc == std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Missing `=` after the variable name in: "
- << envmod << std::endl);
- err_occurred = true;
- continue;
- }
- auto const name = envmod.substr(0, eq_loc);
-
- // Split value on `:`
- auto const op_value_start = eq_loc + 1;
- auto const colon_loc = envmod.find_first_of(':', op_value_start);
- if (colon_loc == std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Missing `:` after the operation in: " << envmod
- << std::endl);
- err_occurred = true;
- continue;
- }
- auto const op =
- envmod.substr(op_value_start, colon_loc - op_value_start);
-
- auto const value_start = colon_loc + 1;
- auto const value = envmod.substr(value_start);
-
- // Determine what to do with the operation.
- if (op == "reset"_s) {
- auto entry = env_application.find(name);
- if (entry != env_application.end()) {
- env_application.erase(entry);
- }
- } else if (op == "set"_s) {
- env_application[name] = value;
- } else if (op == "unset"_s) {
- env_application[name] = {};
- } else if (op == "string_append"_s) {
- apply_diff(name, [&value](std::string& output) { output += value; });
- } else if (op == "string_prepend"_s) {
- apply_diff(name,
- [&value](std::string& output) { output.insert(0, value); });
- } else if (op == "path_list_append"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output += path_sep;
- }
- output += value;
- });
- } else if (op == "path_list_prepend"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), path_sep);
- }
- output.insert(0, value);
- });
- } else if (op == "cmake_list_append"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output += ';';
- }
- output += value;
- });
- } else if (op == "cmake_list_prepend"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), ';');
- }
- output.insert(0, value);
- });
- } else {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Unrecognized environment manipulation argument: "
- << op << std::endl);
- err_occurred = true;
- continue;
- }
+ env_ok &= diff.ParseOperation(envmod);
}
- if (err_occurred) {
+ if (!env_ok) {
return false;
}
- for (auto const& env_apply : env_application) {
- if (env_apply.second) {
- auto const env_update =
- cmStrCat(env_apply.first, '=', *env_apply.second);
- cmSystemTools::PutEnv(env_update);
- envMeasurement << env_update << std::endl;
- } else {
- cmSystemTools::UnsetEnv(env_apply.first.c_str());
- // Signify that this variable is being actively unset
- envMeasurement << "#" << env_apply.first << "=" << std::endl;
- }
- }
+ diff.ApplyToCurrentEnv(&envMeasurement);
}
if (this->UseAllocatedResources) {
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index a2dc61553..a1933cccb 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -8,7 +8,6 @@
#include <cm/memory>
#include <cm/vector>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -87,7 +86,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If FILES are given, but not PARTS, only the FILES are submitted
// and *no* PARTS are submitted.
// (This is why we select the empty "noParts" set in the
- // FilesMentioned block below...)
+ // if(this->Files) block below...)
//
// If PARTS are given, only the selected PARTS are submitted.
//
@@ -96,7 +95,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If given explicit FILES to submit, pass them to the handler.
//
- if (this->FilesMentioned) {
+ if (this->Files) {
// Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
// were also explicitly mentioned, they will be selected below...
// But FILES with no PARTS mentioned should just submit the FILES
@@ -104,14 +103,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
//
handler->SelectParts(std::set<cmCTest::Part>());
handler->SelectFiles(
- std::set<std::string>(this->Files.begin(), this->Files.end()));
+ std::set<std::string>(this->Files->begin(), this->Files->end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
- if (this->PartsMentioned) {
+ if (this->Parts) {
auto parts =
- cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ cmMakeRange(*(this->Parts)).transform([this](std::string const& arg) {
return this->CTest->GetPartFromName(arg);
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
@@ -172,33 +171,31 @@ void cmCTestSubmitCommand::BindArguments()
this->cmCTestHandlerCommand::BindArguments();
}
-void cmCTestSubmitCommand::CheckArguments(
- std::vector<std::string> const& keywords)
+void cmCTestSubmitCommand::CheckArguments()
{
- this->PartsMentioned =
- !this->Parts.empty() || cm::contains(keywords, "PARTS");
- this->FilesMentioned =
- !this->Files.empty() || cm::contains(keywords, "FILES");
-
- cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
- cmCTest::Part p = this->CTest->GetPartFromName(arg);
- if (p == cmCTest::PartCount) {
- std::ostringstream e;
- e << "Part name \"" << arg << "\" is invalid.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
-
- cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
- if (!cmSystemTools::FileExists(arg)) {
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
+ if (this->Parts) {
+ cm::erase_if(*(this->Parts), [this](std::string const& arg) -> bool {
+ cmCTest::Part p = this->CTest->GetPartFromName(arg);
+ if (p == cmCTest::PartCount) {
+ std::ostringstream e;
+ e << "Part name \"" << arg << "\" is invalid.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
+
+ if (this->Files) {
+ cm::erase_if(*(this->Files), [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index c5d11dfd8..b67f18206 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -8,6 +8,9 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
class cmCommand;
@@ -35,13 +38,11 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
bool CDashUpload = false;
- bool FilesMentioned = false;
bool InternalTest = false;
- bool PartsMentioned = false;
std::string BuildID;
std::string CDashUploadFile;
@@ -50,7 +51,7 @@ protected:
std::string RetryDelay;
std::string SubmitURL;
- std::vector<std::string> Files;
- std::vector<std::string> HttpHeaders;
- std::vector<std::string> Parts;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> HttpHeaders;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Parts;
};
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index f86ee0d7c..2ed671c3e 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -21,7 +21,7 @@ void cmCTestUploadCommand::BindArguments()
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestUploadCommand::CheckArguments()
{
cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
if (!cmSystemTools::FileExists(arg)) {
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index fe155f670..a9d1dd249 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -10,6 +10,7 @@
#include <cm/memory>
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -42,8 +43,8 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const&) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
- std::vector<std::string> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Files;
};
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index b14a75175..6e6f0d662 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -85,7 +85,7 @@ void cmCursesLongMessageForm::UpdateStatusBar()
for (size_t i = 0; i < sideSpace; i++) {
version[i] = ' ';
}
- sprintf(version + sideSpace, "%s", vertmp);
+ snprintf(version + sideSpace, sizeof(version) - sideSpace, "%s", vertmp);
version[width] = '\0';
char fmt_s[] = "%s";
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 68d28c839..63214e303 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -11,7 +11,7 @@ elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
endif()
-configure_file(cmFormConfigure.h.in "${CMAKE_CURRENT_BINARY_DIR}/cmFormConfigure.h")
+configure_file(cmFormConfigure.h.in cmFormConfigure.h)
add_library(cmForm
fld_arg.c
diff --git a/Source/CursesDialog/form/fty_int.c b/Source/CursesDialog/form/fty_int.c
index 7107fcc3f..7aeb4b854 100644
--- a/Source/CursesDialog/form/fty_int.c
+++ b/Source/CursesDialog/form/fty_int.c
@@ -117,7 +117,7 @@ static bool Check_Integer_Field(FIELD * field, const void * argp)
{
if (val<low || val>high) return FALSE;
}
- sprintf(buf,"%.*ld",(prec>0?prec:0),val);
+ snprintf(buf,sizeof(buf),"%.*ld",(prec>0?prec:0),val);
set_field_buffer(field,0,buf);
return TRUE;
}
diff --git a/Source/CursesDialog/form/fty_num.c b/Source/CursesDialog/form/fty_num.c
index 78095995f..4109b6fb9 100644
--- a/Source/CursesDialog/form/fty_num.c
+++ b/Source/CursesDialog/form/fty_num.c
@@ -140,7 +140,7 @@ static bool Check_Numeric_Field(FIELD * field, const void * argp)
{
if (val<low || val>high) return FALSE;
}
- sprintf(buf,"%.*f",(prec>0?prec:0),val);
+ snprintf(buf,sizeof(buf),"%.*f",(prec>0?prec:0),val);
set_field_buffer(field,0,buf);
return TRUE;
}
diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx
index c3d000004..5703de14e 100644
--- a/Source/LexerParser/cmFortranLexer.cxx
+++ b/Source/LexerParser/cmFortranLexer.cxx
@@ -557,31 +557,32 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[210] =
+static const flex_int16_t yy_accept[216] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55, 49, 51, 50, 53, 1, 49, 33, 2, 47,
48, 35, 37, 50, 39, 49, 46, 46, 46, 46,
- 46, 46, 49, 46, 51, 49, 50, 49, 46, 9,
- 8, 9, 4, 3, 49, 0, 10, 0, 0, 0,
- 0, 0, 33, 33, 34, 36, 39, 49, 46, 46,
- 46, 46, 46, 46, 0, 52, 46, 0, 0, 0,
- 12, 0, 0, 0, 0, 0, 0, 49, 0, 11,
- 46, 0, 0, 5, 0, 0, 0, 0, 29, 0,
- 33, 33, 33, 33, 0, 0, 40, 46, 46, 46,
-
- 46, 45, 12, 12, 0, 0, 0, 23, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 46, 46, 46, 46, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 30, 31, 0, 0, 0, 0, 0, 46, 46,
- 46, 46, 0, 24, 25, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 20, 32, 27, 0, 0, 0,
- 46, 46, 43, 46, 0, 26, 21, 0, 0, 0,
- 19, 0, 0, 18, 28, 0, 0, 41, 46, 46,
- 17, 22, 0, 7, 38, 7, 15, 0, 46, 46,
-
- 14, 16, 42, 44, 0, 0, 0, 13, 0
+ 46, 46, 49, 46, 51, 49, 50, 51, 49, 46,
+ 9, 8, 9, 9, 4, 3, 49, 0, 10, 0,
+ 0, 0, 0, 0, 33, 33, 34, 36, 39, 49,
+ 46, 46, 46, 46, 46, 46, 0, 52, 0, 46,
+ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0,
+ 0, 49, 0, 11, 46, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 29, 0, 33, 33, 33, 33,
+
+ 0, 0, 40, 46, 46, 46, 46, 45, 12, 12,
+ 0, 0, 0, 23, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 46, 46, 46, 46, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 30, 31, 0,
+ 0, 0, 0, 0, 46, 46, 46, 46, 0, 24,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 20, 32, 27, 0, 0, 0, 46, 46, 43, 46,
+ 0, 26, 21, 0, 0, 0, 19, 0, 0, 18,
+ 28, 0, 0, 41, 46, 46, 17, 22, 0, 7,
+
+ 38, 7, 15, 0, 46, 46, 14, 16, 42, 44,
+ 0, 0, 0, 13, 0
} ;
static const YY_CHAR yy_ec[256] =
@@ -618,189 +619,197 @@ static const YY_CHAR yy_ec[256] =
static const YY_CHAR yy_meta[50] =
{ 0,
- 1, 2, 2, 3, 4, 3, 3, 1, 1, 3,
- 3, 3, 3, 1, 3, 5, 3, 3, 1, 3,
+ 1, 2, 2, 2, 3, 4, 4, 1, 1, 4,
+ 4, 4, 4, 1, 4, 5, 4, 4, 1, 4,
6, 1, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 1, 5,
7, 7, 7, 7, 7, 7, 7, 7, 7
} ;
-static const flex_int16_t yy_base[219] =
+static const flex_int16_t yy_base[225] =
{ 0,
- 0, 48, 0, 49, 464, 56, 52, 57, 62, 68,
- 466, 0, 468, 468, 462, 468, 74, 81, 468, 468,
- 468, 468, 447, 468, 442, 440, 0, 19, 41, 427,
- 47, 41, 90, 119, 97, 158, 455, 207, 247, 468,
- 454, 101, 468, 468, 0, 455, 468, 105, 430, 423,
- 62, 67, 119, 151, 468, 468, 468, 121, 0, 90,
- 93, 110, 431, 112, 142, 468, 0, 160, 295, 0,
- 162, 411, 123, 102, 408, 405, 446, 344, 447, 468,
- 0, 444, 170, 174, 420, 421, 132, 404, 95, 404,
- 180, 186, 192, 228, 297, 397, 0, 168, 144, 52,
-
- 411, 0, 204, 217, 397, 179, 390, 170, 389, 378,
- 364, 390, 389, 230, 468, 363, 355, 337, 337, 334,
- 335, 335, 330, 334, 187, 339, 267, 339, 327, 327,
- 327, 324, 325, 325, 318, 319, 318, 354, 352, 323,
- 327, 468, 468, 310, 307, 305, 297, 297, 275, 275,
- 277, 279, 287, 468, 468, 286, 283, 273, 196, 307,
- 200, 238, 234, 210, 468, 468, 468, 174, 171, 162,
- 279, 182, 0, 269, 150, 468, 468, 137, 109, 323,
- 468, 239, 0, 468, 468, 72, 71, 0, 283, 283,
- 468, 468, 51, 468, 468, 468, 468, 37, 283, 288,
-
- 330, 468, 0, 0, 331, 0, 52, 468, 468, 384,
- 391, 397, 400, 407, 414, 421, 428, 435
+ 0, 48, 0, 49, 55, 58, 64, 66, 75, 83,
+ 491, 0, 492, 492, 487, 492, 86, 92, 492, 492,
+ 492, 492, 472, 492, 467, 465, 0, 56, 59, 452,
+ 66, 16, 105, 131, 109, 170, 480, 481, 219, 259,
+ 492, 478, 479, 116, 492, 492, 0, 478, 492, 111,
+ 453, 446, 34, 78, 155, 174, 492, 492, 492, 121,
+ 0, 29, 105, 101, 454, 101, 131, 492, 474, 0,
+ 180, 307, 0, 146, 433, 117, 94, 430, 427, 468,
+ 467, 356, 468, 492, 0, 465, 464, 187, 191, 465,
+ 439, 440, 149, 423, 126, 423, 200, 240, 311, 322,
+
+ 206, 416, 0, 152, 180, 176, 430, 0, 216, 224,
+ 417, 186, 418, 127, 418, 411, 415, 451, 450, 247,
+ 492, 423, 416, 398, 393, 373, 364, 364, 359, 353,
+ 198, 358, 178, 358, 346, 346, 346, 343, 344, 344,
+ 338, 340, 339, 376, 374, 343, 346, 492, 492, 329,
+ 325, 324, 313, 315, 211, 211, 291, 293, 313, 492,
+ 492, 314, 304, 304, 261, 328, 212, 249, 243, 203,
+ 492, 492, 492, 173, 158, 150, 293, 172, 0, 273,
+ 144, 492, 492, 137, 125, 335, 492, 339, 0, 492,
+ 492, 112, 63, 0, 304, 300, 492, 492, 58, 492,
+
+ 492, 492, 492, 30, 311, 312, 361, 492, 0, 0,
+ 366, 0, 44, 492, 492, 396, 403, 409, 412, 419,
+ 426, 433, 440, 447
} ;
-static const flex_int16_t yy_def[219] =
+static const flex_int16_t yy_def[225] =
{ 0,
- 209, 1, 1, 1, 1, 1, 210, 210, 210, 210,
- 209, 211, 209, 209, 212, 209, 211, 209, 209, 209,
- 209, 209, 209, 209, 209, 211, 213, 213, 213, 213,
- 213, 213, 211, 213, 209, 211, 209, 214, 209, 209,
- 209, 209, 209, 209, 211, 212, 209, 209, 209, 209,
- 209, 209, 209, 215, 209, 209, 209, 211, 213, 213,
- 213, 213, 213, 213, 209, 209, 34, 209, 209, 69,
- 211, 209, 209, 209, 209, 209, 209, 214, 214, 209,
- 39, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 215, 215, 215, 215, 209, 209, 213, 213, 213, 213,
-
- 213, 213, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 213, 213, 213, 213, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 213, 213,
- 213, 213, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 213, 213, 213, 213, 209, 209, 209, 209, 209, 209,
- 209, 216, 217, 209, 209, 209, 209, 213, 213, 213,
- 209, 209, 209, 209, 209, 209, 209, 209, 213, 213,
-
- 209, 209, 213, 213, 209, 218, 218, 209, 0, 209,
- 209, 209, 209, 209, 209, 209, 209, 209
+ 215, 1, 1, 1, 1, 1, 216, 216, 216, 216,
+ 215, 217, 215, 215, 218, 215, 217, 215, 215, 215,
+ 215, 215, 215, 215, 215, 217, 219, 219, 219, 219,
+ 219, 219, 217, 219, 215, 217, 215, 215, 220, 215,
+ 215, 215, 215, 215, 215, 215, 217, 218, 215, 215,
+ 215, 215, 215, 215, 215, 221, 215, 215, 215, 217,
+ 219, 219, 219, 219, 219, 219, 215, 215, 215, 34,
+ 215, 215, 72, 217, 215, 215, 215, 215, 215, 215,
+ 215, 220, 220, 215, 40, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 221, 221, 221, 221,
+
+ 215, 215, 219, 219, 219, 219, 219, 219, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 219, 219, 219, 219, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 219, 219, 219, 219, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 219, 219, 219, 219,
+ 215, 215, 215, 215, 215, 215, 215, 222, 223, 215,
+ 215, 215, 215, 219, 219, 219, 215, 215, 215, 215,
+
+ 215, 215, 215, 215, 219, 219, 215, 215, 219, 219,
+ 215, 224, 224, 215, 0, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215
} ;
-static const flex_int16_t yy_nxt[518] =
+static const flex_int16_t yy_nxt[542] =
{ 0,
12, 13, 14, 13, 13, 15, 16, 12, 17, 18,
19, 20, 21, 12, 22, 12, 23, 24, 12, 25,
12, 26, 27, 27, 27, 27, 28, 27, 27, 29,
27, 30, 27, 27, 27, 31, 27, 32, 33, 34,
27, 27, 28, 27, 29, 27, 27, 31, 32, 35,
- 35, 60, 35, 35, 41, 36, 36, 35, 37, 41,
- 35, 42, 43, 36, 41, 60, 42, 43, 44, 38,
- 41, 42, 208, 61, 44, 48, 64, 42, 48, 202,
- 39, 39, 53, 53, 63, 53, 54, 61, 64, 127,
- 55, 65, 66, 201, 65, 63, 39, 39, 68, 49,
-
- 127, 68, 83, 84, 69, 83, 48, 87, 88, 48,
- 89, 50, 198, 90, 197, 97, 51, 98, 52, 45,
- 53, 53, 95, 53, 54, 95, 45, 45, 55, 99,
- 49, 97, 45, 98, 67, 100, 121, 45, 102, 45,
- 45, 122, 50, 65, 66, 108, 65, 51, 109, 52,
- 193, 100, 92, 53, 102, 92, 93, 45, 67, 70,
- 94, 68, 70, 104, 68, 96, 104, 69, 106, 107,
- 126, 83, 84, 71, 83, 114, 118, 71, 114, 119,
- 192, 92, 53, 115, 92, 93, 126, 92, 53, 94,
- 92, 93, 191, 92, 53, 94, 92, 93, 125, 72,
-
- 73, 94, 74, 75, 189, 104, 76, 78, 104, 80,
- 187, 133, 186, 125, 78, 78, 134, 185, 104, 103,
- 78, 104, 78, 130, 149, 78, 131, 78, 78, 92,
- 53, 114, 92, 93, 114, 149, 184, 94, 183, 115,
- 195, 195, 182, 181, 179, 78, 78, 79, 79, 80,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 81, 79, 79, 79, 79, 79, 79, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 79, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 70, 151, 95, 70,
-
- 171, 95, 172, 173, 174, 188, 190, 199, 180, 203,
- 103, 180, 151, 200, 204, 178, 171, 190, 172, 173,
- 174, 188, 103, 199, 180, 203, 177, 180, 200, 176,
- 204, 205, 205, 175, 205, 205, 72, 73, 103, 74,
- 75, 96, 170, 76, 78, 169, 80, 168, 206, 206,
- 167, 78, 78, 166, 165, 164, 163, 78, 162, 78,
- 161, 160, 78, 159, 78, 78, 158, 157, 156, 155,
- 154, 153, 152, 150, 148, 147, 146, 145, 144, 143,
- 142, 141, 78, 78, 40, 40, 40, 40, 40, 40,
- 40, 45, 140, 139, 138, 45, 45, 46, 46, 46,
-
- 46, 46, 46, 46, 59, 137, 59, 79, 79, 79,
- 79, 79, 79, 79, 91, 91, 91, 91, 91, 91,
- 91, 194, 194, 194, 136, 194, 194, 194, 196, 135,
- 196, 132, 196, 196, 196, 207, 207, 207, 207, 207,
- 129, 207, 128, 124, 123, 120, 117, 116, 113, 80,
- 112, 111, 110, 105, 101, 86, 85, 47, 82, 77,
- 62, 58, 57, 56, 47, 209, 37, 11, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
-
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209
+ 35, 66, 35, 35, 103, 36, 36, 37, 38, 35,
+ 37, 38, 35, 66, 214, 36, 42, 43, 42, 43,
+ 103, 39, 208, 44, 45, 44, 45, 42, 43, 93,
+ 94, 46, 40, 40, 44, 42, 43, 50, 62, 46,
+ 50, 63, 44, 55, 55, 55, 55, 56, 40, 40,
+
+ 207, 57, 62, 65, 204, 63, 67, 68, 69, 67,
+ 71, 51, 50, 71, 65, 50, 72, 88, 89, 90,
+ 88, 95, 101, 52, 96, 101, 106, 108, 53, 104,
+ 54, 47, 67, 68, 69, 67, 51, 114, 47, 47,
+ 115, 105, 106, 108, 47, 104, 70, 110, 52, 47,
+ 110, 47, 47, 53, 203, 54, 55, 55, 55, 55,
+ 56, 74, 112, 113, 57, 102, 199, 127, 139, 47,
+ 70, 73, 128, 140, 73, 98, 55, 98, 98, 99,
+ 198, 71, 131, 100, 71, 74, 197, 72, 88, 89,
+ 90, 88, 120, 124, 195, 120, 125, 131, 193, 192,
+
+ 121, 98, 55, 98, 98, 99, 132, 101, 157, 100,
+ 101, 75, 76, 133, 77, 78, 191, 110, 79, 82,
+ 110, 84, 132, 157, 133, 110, 82, 82, 110, 190,
+ 136, 109, 82, 137, 82, 155, 177, 82, 178, 82,
+ 82, 98, 55, 98, 98, 99, 155, 189, 120, 100,
+ 102, 120, 177, 188, 178, 187, 121, 82, 82, 83,
+ 83, 84, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 85, 83, 83, 83, 83, 83,
+ 83, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 83, 85, 85,
+
+ 85, 85, 85, 85, 85, 85, 85, 85, 73, 185,
+ 196, 73, 98, 55, 98, 98, 99, 179, 180, 194,
+ 100, 196, 109, 98, 55, 98, 98, 99, 205, 186,
+ 206, 100, 186, 179, 180, 194, 186, 209, 210, 186,
+ 201, 201, 201, 109, 205, 206, 184, 183, 75, 76,
+ 109, 77, 78, 209, 210, 79, 82, 182, 84, 181,
+ 176, 175, 211, 82, 82, 211, 174, 211, 173, 82,
+ 211, 82, 172, 171, 82, 170, 82, 82, 169, 212,
+ 168, 167, 166, 165, 212, 164, 163, 162, 161, 160,
+ 159, 158, 156, 154, 82, 82, 41, 41, 41, 41,
+
+ 41, 41, 41, 47, 153, 152, 151, 47, 47, 48,
+ 48, 48, 48, 48, 48, 48, 61, 150, 61, 83,
+ 83, 83, 83, 83, 83, 83, 97, 97, 97, 97,
+ 97, 97, 97, 200, 200, 149, 200, 200, 200, 200,
+ 202, 148, 147, 202, 202, 202, 202, 213, 213, 213,
+ 213, 213, 146, 213, 145, 144, 143, 142, 141, 138,
+ 135, 134, 130, 129, 126, 123, 122, 89, 86, 119,
+ 84, 80, 118, 117, 116, 111, 68, 107, 92, 91,
+ 49, 87, 86, 81, 80, 64, 60, 59, 58, 49,
+ 215, 11, 215, 215, 215, 215, 215, 215, 215, 215,
+
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215
} ;
-static const flex_int16_t yy_chk[518] =
+static const flex_int16_t yy_chk[542] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
- 4, 28, 2, 4, 7, 2, 4, 6, 6, 8,
- 6, 7, 7, 6, 9, 28, 8, 8, 9, 6,
- 10, 9, 207, 29, 10, 17, 32, 10, 17, 198,
- 6, 6, 18, 18, 31, 18, 18, 29, 32, 100,
- 18, 33, 33, 193, 33, 31, 6, 6, 35, 17,
-
- 100, 35, 42, 42, 35, 42, 48, 51, 51, 48,
- 52, 17, 187, 52, 186, 60, 17, 61, 17, 34,
- 53, 53, 58, 53, 53, 58, 34, 34, 53, 61,
- 48, 60, 34, 61, 34, 62, 89, 34, 64, 34,
- 34, 89, 48, 65, 65, 74, 65, 48, 74, 48,
- 179, 62, 54, 54, 64, 54, 54, 34, 34, 36,
- 54, 68, 36, 71, 68, 58, 71, 68, 73, 73,
- 99, 83, 83, 36, 83, 84, 87, 71, 84, 87,
- 178, 91, 91, 84, 91, 91, 99, 92, 92, 91,
- 92, 92, 175, 93, 93, 92, 93, 93, 98, 36,
-
- 36, 93, 36, 36, 172, 103, 36, 38, 103, 38,
- 170, 108, 169, 98, 38, 38, 108, 168, 104, 103,
- 38, 104, 38, 106, 125, 38, 106, 38, 38, 94,
- 94, 114, 94, 94, 114, 125, 164, 94, 163, 114,
- 182, 182, 162, 161, 159, 38, 38, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 69, 127, 95, 69,
-
- 149, 95, 150, 151, 152, 171, 174, 189, 160, 199,
- 69, 160, 127, 190, 200, 158, 149, 174, 150, 151,
- 152, 171, 160, 189, 180, 199, 157, 180, 190, 156,
- 200, 201, 205, 153, 201, 205, 69, 69, 180, 69,
- 69, 95, 148, 69, 78, 147, 78, 146, 201, 205,
- 145, 78, 78, 144, 141, 140, 139, 78, 138, 78,
- 137, 136, 78, 135, 78, 78, 134, 133, 132, 131,
- 130, 129, 128, 126, 124, 123, 122, 121, 120, 119,
- 118, 117, 78, 78, 210, 210, 210, 210, 210, 210,
- 210, 211, 116, 113, 112, 211, 211, 212, 212, 212,
-
- 212, 212, 212, 212, 213, 111, 213, 214, 214, 214,
- 214, 214, 214, 214, 215, 215, 215, 215, 215, 215,
- 215, 216, 216, 216, 110, 216, 216, 216, 217, 109,
- 217, 107, 217, 217, 217, 218, 218, 218, 218, 218,
- 105, 218, 101, 96, 90, 88, 86, 85, 82, 79,
- 77, 76, 75, 72, 63, 50, 49, 46, 41, 37,
- 30, 26, 25, 23, 15, 11, 5, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
-
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209
+ 4, 32, 2, 4, 62, 2, 4, 5, 5, 6,
+ 6, 6, 6, 32, 213, 6, 7, 7, 8, 8,
+ 62, 6, 204, 7, 7, 8, 8, 9, 9, 53,
+ 53, 9, 6, 6, 9, 10, 10, 17, 28, 10,
+ 17, 29, 10, 18, 18, 18, 18, 18, 6, 6,
+
+ 199, 18, 28, 31, 193, 29, 33, 33, 33, 33,
+ 35, 17, 50, 35, 31, 50, 35, 44, 44, 44,
+ 44, 54, 60, 17, 54, 60, 64, 66, 17, 63,
+ 17, 34, 67, 67, 67, 67, 50, 77, 34, 34,
+ 77, 63, 64, 66, 34, 63, 34, 74, 50, 34,
+ 74, 34, 34, 50, 192, 50, 55, 55, 55, 55,
+ 55, 74, 76, 76, 55, 60, 185, 95, 114, 34,
+ 34, 36, 95, 114, 36, 56, 56, 56, 56, 56,
+ 184, 71, 104, 56, 71, 36, 181, 71, 88, 88,
+ 88, 88, 89, 93, 178, 89, 93, 104, 176, 175,
+
+ 89, 97, 97, 97, 97, 97, 105, 101, 133, 97,
+ 101, 36, 36, 106, 36, 36, 174, 109, 36, 39,
+ 109, 39, 105, 133, 106, 110, 39, 39, 110, 170,
+ 112, 109, 39, 112, 39, 131, 155, 39, 156, 39,
+ 39, 98, 98, 98, 98, 98, 131, 169, 120, 98,
+ 101, 120, 155, 168, 156, 167, 120, 39, 39, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+
+ 40, 40, 40, 40, 40, 40, 40, 40, 72, 165,
+ 180, 72, 99, 99, 99, 99, 99, 157, 158, 177,
+ 99, 180, 72, 100, 100, 100, 100, 100, 195, 166,
+ 196, 100, 166, 157, 158, 177, 186, 205, 206, 186,
+ 188, 188, 188, 166, 195, 196, 164, 163, 72, 72,
+ 186, 72, 72, 205, 206, 72, 82, 162, 82, 159,
+ 154, 153, 207, 82, 82, 207, 152, 211, 151, 82,
+ 211, 82, 150, 147, 82, 146, 82, 82, 145, 207,
+ 144, 143, 142, 141, 211, 140, 139, 138, 137, 136,
+ 135, 134, 132, 130, 82, 82, 216, 216, 216, 216,
+
+ 216, 216, 216, 217, 129, 128, 127, 217, 217, 218,
+ 218, 218, 218, 218, 218, 218, 219, 126, 219, 220,
+ 220, 220, 220, 220, 220, 220, 221, 221, 221, 221,
+ 221, 221, 221, 222, 222, 125, 222, 222, 222, 222,
+ 223, 124, 123, 223, 223, 223, 223, 224, 224, 224,
+ 224, 224, 122, 224, 119, 118, 117, 116, 115, 113,
+ 111, 107, 102, 96, 94, 92, 91, 90, 87, 86,
+ 83, 81, 80, 79, 78, 75, 69, 65, 52, 51,
+ 48, 43, 42, 38, 37, 30, 26, 25, 23, 15,
+ 11, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215
} ;
/* The intent behind this definition is that it'll catch
@@ -1139,13 +1148,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 210 )
+ if ( yy_current_state >= 216 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 468 );
+ while ( yy_base[yy_current_state] != 492 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1733,7 +1742,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 210 )
+ if ( yy_current_state >= 216 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1762,11 +1771,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 210 )
+ if ( yy_current_state >= 216 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 209);
+ yy_is_jam = (yy_current_state == 215);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l
index 05769a1e3..fac3181b4 100644
--- a/Source/LexerParser/cmFortranLexer.in.l
+++ b/Source/LexerParser/cmFortranLexer.in.l
@@ -75,10 +75,10 @@ Modify cmFortranLexer.cxx:
return STRING;
}
-<str_dq,str_sq>&[ \t]*\n |
-<str_dq,str_sq>&[ \t]*\n[ \t]*& /* Ignore (continued strings, free fmt) */
+<str_dq,str_sq>&[ \t]*\r?\n |
+<str_dq,str_sq>&[ \t]*\r?\n[ \t]*& /* Ignore (continued strings, free fmt) */
-<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] {
+<fixed_fmt,str_dq,str_sq>\r?\n[ ]{5}[^ \t\r\n] {
if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
; /* Ignore (cont. strings, fixed fmt) */
else
@@ -132,15 +132,15 @@ $[ \t]*else { return F90PPR_ELSE; }
$[ \t]*endif { return F90PPR_ENDIF; }
/* Line continuations, possible involving comments. */
-&([ \t\n]*|!.*)*
-&([ \t\n]*|!.*)*&
+&([ \t\r\n]*|!.*)*
+&([ \t\r\n]*|!.*)*&
, { return COMMA; }
:: { return DCOLON; }
: { return COLON; }
-<fixed_fmt>\n[ ]{5}[^ ] { return GARBAGE; }
+<fixed_fmt>\r?\n[ ]{5}[^ ] { return GARBAGE; }
=|=> { return ASSIGNMENT_OP; }
@@ -159,13 +159,13 @@ $[ \t]*endif { return F90PPR_ENDIF; }
\( { return LPAREN; }
\) { return RPAREN; }
-[^ \t\n\r:;,!'"a-zA-Z=&()]+ { return GARBAGE; }
+[^ \t\r\n:;,!'"a-zA-Z=&()]+ { return GARBAGE; }
;|\n { return EOSTMT; }
[ \t\r,] /* Ignore */
-\\[ \t]*\n /* Ignore line-endings preceded by \ */
+\\[ \t]*\r?\n /* Ignore line-endings preceded by \ */
. { return *yytext; }
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index b177296ac..5e5cc0be6 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -548,7 +548,7 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 594
+#define YYLAST 432
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 41
@@ -557,7 +557,7 @@ union yyalloc
/* YYNRULES -- Number of rules. */
#define YYNRULES 64
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 127
+#define YYNSTATES 121
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 295
@@ -608,15 +608,15 @@ static const yytype_int8 yytranslate[] =
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
-static const yytype_int16 yyrline[] =
+static const yytype_uint8 yyrline[] =
{
- 0, 106, 106, 106, 109, 113, 118, 127, 133, 140,
- 145, 149, 154, 166, 171, 176, 181, 186, 191, 196,
- 201, 206, 210, 214, 218, 222, 223, 228, 228, 228,
- 229, 229, 230, 230, 231, 231, 232, 232, 233, 233,
- 234, 234, 235, 235, 236, 236, 237, 237, 240, 241,
- 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
- 252, 253, 254, 255, 256
+ 0, 106, 106, 106, 109, 113, 118, 123, 129, 136,
+ 141, 145, 150, 162, 167, 172, 177, 182, 187, 192,
+ 197, 202, 206, 210, 214, 218, 219, 224, 224, 224,
+ 225, 225, 226, 226, 227, 227, 228, 228, 229, 229,
+ 230, 230, 231, 231, 232, 232, 233, 233, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252
};
#endif
@@ -666,19 +666,19 @@ yysymbol_name (yysymbol_kind_t yysymbol)
STATE-NUM. */
static const yytype_int16 yypact[] =
{
- -39, 21, -39, 1, -39, -20, -39, -39, -39, -39,
+ -39, 21, -39, 5, -39, -23, -39, -39, -39, -39,
-39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
- -39, -39, -39, -39, -39, -39, -24, -18, 20, -8,
- -3, 40, -39, 15, 16, 17, 19, 34, -39, -39,
- -39, -39, -39, -39, 59, -39, -39, -39, -39, -39,
- 36, 37, 38, -39, -39, -39, -39, -39, -39, 77,
- 115, 130, 168, 183, -39, -39, -39, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -25, -19, 20, -8,
+ -15, -22, -39, -6, 14, 15, 16, 17, -39, -39,
+ -39, -39, -39, -39, 59, 49, 51, -39, 63, 64,
+ 35, 36, 37, -39, -39, -39, -39, -39, -39, 74,
+ 112, 127, 165, 180, -39, -39, -39, -39, -39, -39,
-39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
- -39, -39, -39, 221, 236, 274, 289, -21, 26, -39,
- 327, 342, 380, 395, 433, 448, -39, -39, -39, -39,
- -39, -39, -39, -39, -39, 39, 41, 42, 486, -39,
- -39, -39, -39, -39, -39, 18, -39, -39, -39, 43,
- 501, 539, -39, -39, -39, 554, -39
+ -39, -39, -39, -39, -39, -39, -39, -20, 43, -39,
+ 218, 233, 271, 286, 324, 339, -39, -39, -39, -39,
+ -39, 39, 40, 41, 377, -39, -39, -39, -39, -39,
+ -39, 46, 78, -39, -39, 50, -39, 392, 79, -39,
+ -39
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -690,15 +690,15 @@ static const yytype_int8 yydefact[] =
30, 33, 32, 34, 36, 38, 42, 40, 44, 35,
37, 39, 43, 41, 45, 46, 0, 0, 0, 0,
0, 0, 3, 0, 0, 0, 0, 0, 46, 46,
- 46, 46, 26, 46, 0, 46, 46, 4, 46, 46,
+ 46, 46, 26, 46, 0, 0, 0, 4, 0, 0,
0, 0, 0, 46, 46, 46, 46, 46, 46, 0,
0, 0, 0, 0, 15, 57, 56, 64, 62, 58,
59, 60, 61, 63, 55, 48, 49, 50, 51, 52,
- 53, 54, 47, 0, 0, 0, 0, 0, 0, 46,
+ 53, 54, 47, 10, 13, 9, 6, 0, 0, 46,
0, 0, 0, 0, 0, 0, 21, 22, 23, 24,
- 14, 10, 13, 9, 6, 0, 0, 0, 0, 5,
- 16, 17, 18, 19, 20, 0, 46, 46, 11, 0,
- 0, 0, 46, 7, 12, 0, 8
+ 14, 0, 0, 0, 0, 5, 16, 17, 18, 19,
+ 20, 0, 0, 46, 11, 0, 7, 0, 0, 12,
+ 8
};
/* YYPGOTO[NTERM-NUM]. */
@@ -720,81 +720,70 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int8 yytable[] =
{
- 59, 60, 61, 62, 42, 63, 105, 83, 84, 106,
- 85, 86, 43, 45, 46, 90, 91, 92, 93, 94,
- 95, 2, 3, 47, 4, 49, 50, 5, 6, 7,
+ 59, 60, 61, 62, 51, 63, 52, 101, 42, 43,
+ 102, 53, 45, 46, 50, 90, 91, 92, 93, 94,
+ 95, 2, 3, 47, 4, 49, 54, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 54, 119, 55,
- 56, 108, 57, 48, 107, 25, 26, 27, 28, 29,
- 30, 31, 64, 65, 66, 67, 51, 58, 52, 87,
- 88, 89, 115, 53, 116, 117, 122, 0, 120, 121,
- 96, 65, 66, 67, 125, 68, 69, 70, 71, 72,
+ 18, 19, 20, 21, 22, 23, 24, 55, 56, 57,
+ 58, 104, 83, 48, 84, 25, 26, 27, 28, 29,
+ 30, 31, 64, 65, 66, 67, 85, 86, 87, 88,
+ 89, 103, 111, 112, 113, 117, 115, 96, 65, 66,
+ 67, 116, 120, 118, 0, 68, 69, 70, 71, 72,
73, 74, 75, 0, 76, 77, 78, 79, 80, 81,
- 0, 0, 0, 68, 69, 70, 71, 72, 73, 74,
- 75, 0, 76, 77, 78, 79, 80, 81, 97, 65,
+ 68, 69, 70, 71, 72, 73, 74, 75, 0, 76,
+ 77, 78, 79, 80, 81, 97, 65, 66, 67, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 65, 66, 67, 0, 0, 0, 0, 68, 69,
+ 70, 71, 72, 73, 74, 75, 0, 76, 77, 78,
+ 79, 80, 81, 68, 69, 70, 71, 72, 73, 74,
+ 75, 0, 76, 77, 78, 79, 80, 81, 99, 65,
66, 67, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 98, 65, 66, 67, 0, 0, 0,
+ 0, 0, 0, 100, 65, 66, 67, 0, 0, 0,
0, 68, 69, 70, 71, 72, 73, 74, 75, 0,
76, 77, 78, 79, 80, 81, 68, 69, 70, 71,
72, 73, 74, 75, 0, 76, 77, 78, 79, 80,
- 81, 99, 65, 66, 67, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 100, 65, 66, 67,
+ 81, 105, 65, 66, 67, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 106, 65, 66, 67,
0, 0, 0, 0, 68, 69, 70, 71, 72, 73,
74, 75, 0, 76, 77, 78, 79, 80, 81, 68,
69, 70, 71, 72, 73, 74, 75, 0, 76, 77,
- 78, 79, 80, 81, 101, 65, 66, 67, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 102,
+ 78, 79, 80, 81, 107, 65, 66, 67, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 108,
65, 66, 67, 0, 0, 0, 0, 68, 69, 70,
71, 72, 73, 74, 75, 0, 76, 77, 78, 79,
80, 81, 68, 69, 70, 71, 72, 73, 74, 75,
- 0, 76, 77, 78, 79, 80, 81, 103, 65, 66,
+ 0, 76, 77, 78, 79, 80, 81, 109, 65, 66,
67, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 104, 65, 66, 67, 0, 0, 0, 0,
+ 0, 0, 110, 65, 66, 67, 0, 0, 0, 0,
68, 69, 70, 71, 72, 73, 74, 75, 0, 76,
77, 78, 79, 80, 81, 68, 69, 70, 71, 72,
73, 74, 75, 0, 76, 77, 78, 79, 80, 81,
- 109, 65, 66, 67, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 110, 65, 66, 67, 0,
+ 114, 65, 66, 67, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 119, 65, 66, 67, 0,
0, 0, 0, 68, 69, 70, 71, 72, 73, 74,
75, 0, 76, 77, 78, 79, 80, 81, 68, 69,
70, 71, 72, 73, 74, 75, 0, 76, 77, 78,
- 79, 80, 81, 111, 65, 66, 67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 112, 65,
- 66, 67, 0, 0, 0, 0, 68, 69, 70, 71,
- 72, 73, 74, 75, 0, 76, 77, 78, 79, 80,
- 81, 68, 69, 70, 71, 72, 73, 74, 75, 0,
- 76, 77, 78, 79, 80, 81, 113, 65, 66, 67,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 114, 65, 66, 67, 0, 0, 0, 0, 68,
- 69, 70, 71, 72, 73, 74, 75, 0, 76, 77,
- 78, 79, 80, 81, 68, 69, 70, 71, 72, 73,
- 74, 75, 0, 76, 77, 78, 79, 80, 81, 118,
- 65, 66, 67, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 123, 65, 66, 67, 0, 0,
- 0, 0, 68, 69, 70, 71, 72, 73, 74, 75,
- 0, 76, 77, 78, 79, 80, 81, 68, 69, 70,
- 71, 72, 73, 74, 75, 0, 76, 77, 78, 79,
- 80, 81, 124, 65, 66, 67, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 126, 65, 66,
- 67, 0, 0, 0, 0, 68, 69, 70, 71, 72,
- 73, 74, 75, 0, 76, 77, 78, 79, 80, 81,
- 68, 69, 70, 71, 72, 73, 74, 75, 0, 76,
- 77, 78, 79, 80, 81
+ 79, 80, 81
};
static const yytype_int8 yycheck[] =
{
- 38, 39, 40, 41, 3, 43, 27, 45, 46, 30,
- 48, 49, 32, 37, 32, 53, 54, 55, 56, 57,
- 58, 0, 1, 3, 3, 33, 29, 6, 7, 8,
+ 38, 39, 40, 41, 26, 43, 28, 27, 3, 32,
+ 30, 33, 37, 32, 29, 53, 54, 55, 56, 57,
+ 58, 0, 1, 3, 3, 33, 32, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 32, 30, 33,
- 33, 89, 33, 33, 28, 34, 35, 36, 37, 38,
- 39, 40, 3, 4, 5, 6, 26, 33, 28, 33,
- 33, 33, 33, 33, 33, 33, 33, -1, 116, 117,
- 3, 4, 5, 6, 122, 26, 27, 28, 29, 30,
+ 19, 20, 21, 22, 23, 24, 25, 33, 33, 33,
+ 33, 89, 3, 33, 3, 34, 35, 36, 37, 38,
+ 39, 40, 3, 4, 5, 6, 3, 3, 33, 33,
+ 33, 28, 33, 33, 33, 113, 30, 3, 4, 5,
+ 6, 3, 3, 33, -1, 26, 27, 28, 29, 30,
31, 32, 33, -1, 35, 36, 37, 38, 39, 40,
- -1, -1, -1, 26, 27, 28, 29, 30, 31, 32,
+ 26, 27, 28, 29, 30, 31, 32, 33, -1, 35,
+ 36, 37, 38, 39, 40, 3, 4, 5, 6, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 3, 4, 5, 6, -1, -1, -1, -1, 26, 27,
+ 28, 29, 30, 31, 32, 33, -1, 35, 36, 37,
+ 38, 39, 40, 26, 27, 28, 29, 30, 31, 32,
33, -1, 35, 36, 37, 38, 39, 40, 3, 4,
5, 6, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 3, 4, 5, 6, -1, -1, -1,
@@ -822,28 +811,7 @@ static const yytype_int8 yycheck[] =
-1, -1, -1, 26, 27, 28, 29, 30, 31, 32,
33, -1, 35, 36, 37, 38, 39, 40, 26, 27,
28, 29, 30, 31, 32, 33, -1, 35, 36, 37,
- 38, 39, 40, 3, 4, 5, 6, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 3, 4,
- 5, 6, -1, -1, -1, -1, 26, 27, 28, 29,
- 30, 31, 32, 33, -1, 35, 36, 37, 38, 39,
- 40, 26, 27, 28, 29, 30, 31, 32, 33, -1,
- 35, 36, 37, 38, 39, 40, 3, 4, 5, 6,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3, 4, 5, 6, -1, -1, -1, -1, 26,
- 27, 28, 29, 30, 31, 32, 33, -1, 35, 36,
- 37, 38, 39, 40, 26, 27, 28, 29, 30, 31,
- 32, 33, -1, 35, 36, 37, 38, 39, 40, 3,
- 4, 5, 6, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3, 4, 5, 6, -1, -1,
- -1, -1, 26, 27, 28, 29, 30, 31, 32, 33,
- -1, 35, 36, 37, 38, 39, 40, 26, 27, 28,
- 29, 30, 31, 32, 33, -1, 35, 36, 37, 38,
- 39, 40, 3, 4, 5, 6, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3, 4, 5,
- 6, -1, -1, -1, -1, 26, 27, 28, 29, 30,
- 31, 32, 33, -1, 35, 36, 37, 38, 39, 40,
- 26, 27, 28, 29, 30, 31, 32, 33, -1, 35,
- 36, 37, 38, 39, 40
+ 38, 39, 40
};
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
@@ -858,11 +826,11 @@ static const yytype_int8 yystos[] =
29, 26, 28, 33, 32, 33, 33, 33, 33, 53,
53, 53, 53, 53, 3, 4, 5, 6, 26, 27,
28, 29, 30, 31, 32, 33, 35, 36, 37, 38,
- 39, 40, 54, 53, 53, 53, 53, 33, 33, 33,
+ 39, 40, 54, 3, 3, 3, 3, 33, 33, 33,
53, 53, 53, 53, 53, 53, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 27, 30, 28, 53, 3,
- 3, 3, 3, 3, 3, 33, 33, 33, 3, 30,
- 53, 53, 33, 3, 3, 53, 3
+ 3, 27, 30, 28, 53, 3, 3, 3, 3, 3,
+ 3, 33, 33, 33, 3, 30, 3, 53, 33, 3,
+ 3
};
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
@@ -880,8 +848,8 @@ static const yytype_int8 yyr1[] =
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
static const yytype_int8 yyr2[] =
{
- 0, 2, 0, 2, 2, 4, 4, 7, 9, 4,
- 4, 5, 7, 4, 4, 3, 4, 4, 4, 4,
+ 0, 2, 0, 2, 2, 4, 3, 6, 8, 3,
+ 3, 5, 7, 3, 4, 3, 4, 4, 4, 4,
4, 3, 3, 3, 3, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 2, 1, 1,
@@ -1361,19 +1329,19 @@ yydestruct (const char *yymsg,
case YYSYMBOL_STRING: /* STRING */
#line 100 "cmFortranParser.y"
{ free(((*yyvaluep).string)); }
-#line 1365 "cmFortranParser.cxx"
+#line 1333 "cmFortranParser.cxx"
break;
case YYSYMBOL_WORD: /* WORD */
#line 100 "cmFortranParser.y"
{ free(((*yyvaluep).string)); }
-#line 1371 "cmFortranParser.cxx"
+#line 1339 "cmFortranParser.cxx"
break;
case YYSYMBOL_CPP_INCLUDE_ANGLE: /* CPP_INCLUDE_ANGLE */
#line 100 "cmFortranParser.y"
{ free(((*yyvaluep).string)); }
-#line 1377 "cmFortranParser.cxx"
+#line 1345 "cmFortranParser.cxx"
break;
default:
@@ -1655,7 +1623,7 @@ yyreduce:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
}
-#line 1659 "cmFortranParser.cxx"
+#line 1627 "cmFortranParser.cxx"
break;
case 5: /* stmt: USE WORD other EOSTMT */
@@ -1665,77 +1633,73 @@ yyreduce:
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1669 "cmFortranParser.cxx"
+#line 1637 "cmFortranParser.cxx"
break;
- case 6: /* stmt: MODULE WORD other EOSTMT */
+ case 6: /* stmt: MODULE WORD EOSTMT */
#line 118 "cmFortranParser.y"
- {
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
- cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 &&
- cmsysString_strcasecmp((yyvsp[-2].string), "subroutine") != 0) {
- cmFortranParser_RuleModule(parser, (yyvsp[-2].string));
- }
- free((yyvsp[-2].string));
+ cmFortranParser_RuleModule(parser, (yyvsp[-1].string));
+ free((yyvsp[-1].string));
}
-#line 1683 "cmFortranParser.cxx"
+#line 1647 "cmFortranParser.cxx"
break;
- case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */
-#line 127 "cmFortranParser.y"
- {
+ case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD EOSTMT */
+#line 123 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
- free((yyvsp[-4].string));
- free((yyvsp[-2].string));
+ cmFortranParser_RuleSubmodule(parser, (yyvsp[-3].string), (yyvsp[-1].string));
+ free((yyvsp[-3].string));
+ free((yyvsp[-1].string));
}
-#line 1694 "cmFortranParser.cxx"
+#line 1658 "cmFortranParser.cxx"
break;
- case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */
-#line 133 "cmFortranParser.y"
- {
+ case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD EOSTMT */
+#line 129 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
- free((yyvsp[-6].string));
- free((yyvsp[-4].string));
- free((yyvsp[-2].string));
+ cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-5].string), (yyvsp[-3].string), (yyvsp[-1].string));
+ free((yyvsp[-5].string));
+ free((yyvsp[-3].string));
+ free((yyvsp[-1].string));
}
-#line 1706 "cmFortranParser.cxx"
+#line 1670 "cmFortranParser.cxx"
break;
- case 9: /* stmt: INTERFACE WORD other EOSTMT */
-#line 140 "cmFortranParser.y"
- {
+ case 9: /* stmt: INTERFACE WORD EOSTMT */
+#line 136 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
- free((yyvsp[-2].string));
+ free((yyvsp[-1].string));
}
-#line 1716 "cmFortranParser.cxx"
+#line 1680 "cmFortranParser.cxx"
break;
- case 10: /* stmt: END INTERFACE other EOSTMT */
-#line 145 "cmFortranParser.y"
- {
+ case 10: /* stmt: END INTERFACE EOSTMT */
+#line 141 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
-#line 1725 "cmFortranParser.cxx"
+#line 1689 "cmFortranParser.cxx"
break;
case 11: /* stmt: USE DCOLON WORD other EOSTMT */
-#line 149 "cmFortranParser.y"
+#line 145 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1735 "cmFortranParser.cxx"
+#line 1699 "cmFortranParser.cxx"
break;
case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */
-#line 154 "cmFortranParser.y"
+#line 150 "cmFortranParser.y"
{
if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
@@ -1748,139 +1712,139 @@ yyreduce:
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1752 "cmFortranParser.cxx"
+#line 1716 "cmFortranParser.cxx"
break;
- case 13: /* stmt: INCLUDE STRING other EOSTMT */
-#line 166 "cmFortranParser.y"
- {
+ case 13: /* stmt: INCLUDE STRING EOSTMT */
+#line 162 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
- free((yyvsp[-2].string));
+ cmFortranParser_RuleInclude(parser, (yyvsp[-1].string));
+ free((yyvsp[-1].string));
}
-#line 1762 "cmFortranParser.cxx"
+#line 1726 "cmFortranParser.cxx"
break;
case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
-#line 171 "cmFortranParser.y"
+#line 167 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1772 "cmFortranParser.cxx"
+#line 1736 "cmFortranParser.cxx"
break;
case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
-#line 176 "cmFortranParser.y"
+#line 172 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1782 "cmFortranParser.cxx"
+#line 1746 "cmFortranParser.cxx"
break;
case 16: /* stmt: include STRING other EOSTMT */
-#line 181 "cmFortranParser.y"
+#line 177 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1792 "cmFortranParser.cxx"
+#line 1756 "cmFortranParser.cxx"
break;
case 17: /* stmt: define WORD other EOSTMT */
-#line 186 "cmFortranParser.y"
+#line 182 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1802 "cmFortranParser.cxx"
+#line 1766 "cmFortranParser.cxx"
break;
case 18: /* stmt: undef WORD other EOSTMT */
-#line 191 "cmFortranParser.y"
+#line 187 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1812 "cmFortranParser.cxx"
+#line 1776 "cmFortranParser.cxx"
break;
case 19: /* stmt: ifdef WORD other EOSTMT */
-#line 196 "cmFortranParser.y"
+#line 192 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1822 "cmFortranParser.cxx"
+#line 1786 "cmFortranParser.cxx"
break;
case 20: /* stmt: ifndef WORD other EOSTMT */
-#line 201 "cmFortranParser.y"
+#line 197 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1832 "cmFortranParser.cxx"
+#line 1796 "cmFortranParser.cxx"
break;
case 21: /* stmt: if other EOSTMT */
-#line 206 "cmFortranParser.y"
+#line 202 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1841 "cmFortranParser.cxx"
+#line 1805 "cmFortranParser.cxx"
break;
case 22: /* stmt: elif other EOSTMT */
-#line 210 "cmFortranParser.y"
+#line 206 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1850 "cmFortranParser.cxx"
+#line 1814 "cmFortranParser.cxx"
break;
case 23: /* stmt: else other EOSTMT */
-#line 214 "cmFortranParser.y"
+#line 210 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1859 "cmFortranParser.cxx"
+#line 1823 "cmFortranParser.cxx"
break;
case 24: /* stmt: endif other EOSTMT */
-#line 218 "cmFortranParser.y"
+#line 214 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1868 "cmFortranParser.cxx"
+#line 1832 "cmFortranParser.cxx"
break;
case 48: /* misc_code: WORD */
-#line 240 "cmFortranParser.y"
+#line 236 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1874 "cmFortranParser.cxx"
+#line 1838 "cmFortranParser.cxx"
break;
case 55: /* misc_code: STRING */
-#line 247 "cmFortranParser.y"
+#line 243 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1880 "cmFortranParser.cxx"
+#line 1844 "cmFortranParser.cxx"
break;
-#line 1884 "cmFortranParser.cxx"
+#line 1848 "cmFortranParser.cxx"
default: break;
}
@@ -2104,6 +2068,6 @@ yyreturnlab:
return yyresult;
}
-#line 259 "cmFortranParser.y"
+#line 255 "cmFortranParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index 07ca630f1..a5c897648 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -115,34 +115,30 @@ stmt:
cmFortranParser_RuleUse(parser, $2);
free($2);
}
-| MODULE WORD other EOSTMT {
+| MODULE WORD EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- if (cmsysString_strcasecmp($2, "function") != 0 &&
- cmsysString_strcasecmp($2, "procedure") != 0 &&
- cmsysString_strcasecmp($2, "subroutine") != 0) {
- cmFortranParser_RuleModule(parser, $2);
- }
+ cmFortranParser_RuleModule(parser, $2);
free($2);
}
-| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
+| SUBMODULE LPAREN WORD RPAREN WORD EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmodule(parser, $3, $5);
free($3);
free($5);
}
-| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
+| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7);
free($3);
free($5);
free($7);
}
-| INTERFACE WORD other EOSTMT {
+| INTERFACE WORD EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
free($2);
}
-| END INTERFACE other EOSTMT {
+| END INTERFACE EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
@@ -163,7 +159,7 @@ stmt:
free($3);
free($5);
}
-| INCLUDE STRING other EOSTMT {
+| INCLUDE STRING EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, $2);
free($2);
diff --git a/Source/Modules/CMakeBuildUtilities.cmake b/Source/Modules/CMakeBuildUtilities.cmake
new file mode 100644
index 000000000..5cfb0e76e
--- /dev/null
+++ b/Source/Modules/CMakeBuildUtilities.cmake
@@ -0,0 +1,379 @@
+#-----------------------------------------------------------------------
+# Build the utilities used by CMake
+#
+# Originally it was a macro in the root `CMakeLists.txt` with the comment
+# "Simply to improve readability...".
+# However, as part of the modernization refactoring it was moved into a
+# separate file cuz adding library alises wasn't possible inside the
+# macro.
+#-----------------------------------------------------------------------
+
+# Suppress unnecessary checks in third-party code.
+include(Utilities/cmThirdPartyChecks.cmake)
+
+#---------------------------------------------------------------------
+# Create the kwsys library for CMake.
+set(KWSYS_NAMESPACE cmsys)
+set(KWSYS_USE_SystemTools 1)
+set(KWSYS_USE_Directory 1)
+set(KWSYS_USE_RegularExpression 1)
+set(KWSYS_USE_Base64 1)
+set(KWSYS_USE_MD5 1)
+set(KWSYS_USE_Process 1)
+set(KWSYS_USE_CommandLineArguments 1)
+set(KWSYS_USE_ConsoleBuf 1)
+set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source)
+set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}")
+if(CMake_NO_CXX_STANDARD)
+ set(KWSYS_CXX_STANDARD "")
+endif()
+if(CMake_NO_SELF_BACKTRACE)
+ set(KWSYS_NO_EXECINFO 1)
+endif()
+if(WIN32)
+ # FIXME: Teach KWSys to hard-code these checks on Windows.
+ set(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC_COMPILED 0)
+ set(KWSYS_C_HAS_PTRDIFF_T_COMPILED 1)
+ set(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H_COMPILED 1)
+ set(KWSYS_CXX_HAS_RLIMIT64_COMPILED 0)
+ set(KWSYS_CXX_HAS_SETENV_COMPILED 0)
+ set(KWSYS_CXX_HAS_UNSETENV_COMPILED 0)
+ set(KWSYS_CXX_HAS_UTIMENSAT_COMPILED 0)
+ set(KWSYS_CXX_HAS_UTIMES_COMPILED 0)
+ set(KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED 0)
+ set(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED 0)
+ set(KWSYS_STL_HAS_WSTRING_COMPILED 1)
+ set(KWSYS_SYS_HAS_IFADDRS_H 0)
+endif()
+add_subdirectory(Source/kwsys)
+set(kwsys_folder "Utilities/KWSys")
+CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}")
+CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}")
+if(BUILD_TESTING)
+ CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}")
+ CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}")
+ CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsC "${kwsys_folder}")
+ CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsCxx "${kwsys_folder}")
+ CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestSharedForward "${kwsys_folder}")
+endif()
+
+#---------------------------------------------------------------------
+# Setup third-party libraries.
+# Everything in the tree should be able to include files from the
+# Utilities directory.
+if((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ # using -isystem option generate error "template with C linkage"
+ include_directories("${CMake_SOURCE_DIR}/Utilities/std")
+else()
+ include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities/std")
+endif()
+
+include_directories("${CMake_BINARY_DIR}/Utilities")
+if((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ # using -isystem option generate error "template with C linkage"
+ include_directories("${CMake_SOURCE_DIR}/Utilities")
+else()
+ include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities")
+endif()
+
+#---------------------------------------------------------------------
+# Build CMake std library for CMake and CTest.
+add_subdirectory(Utilities/std)
+CMAKE_SET_TARGET_FOLDER(cmstd "Utilities/std")
+
+# check for the use of system libraries versus builtin ones
+# (a macro defined in this file)
+CMAKE_HANDLE_SYSTEM_LIBRARIES()
+
+if(CMAKE_USE_SYSTEM_KWIML)
+ find_package(KWIML 1.0)
+ if(NOT KWIML_FOUND)
+ message(FATAL_ERROR "CMAKE_USE_SYSTEM_KWIML is ON but KWIML is not found!")
+ endif()
+else()
+ if(BUILD_TESTING)
+ set(KWIML_TEST_ENABLE 1)
+ endif()
+ add_subdirectory(Utilities/KWIML)
+endif()
+
+if(CMAKE_USE_SYSTEM_LIBRHASH)
+ find_package(LibRHash)
+ if(NOT LibRHash_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_LIBRHASH is ON but LibRHash is not found!")
+ endif()
+else()
+ add_subdirectory(Utilities/cmlibrhash)
+ add_library(LibRHash::LibRHash ALIAS cmlibrhash)
+ CMAKE_SET_TARGET_FOLDER(cmlibrhash "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Build zlib library for Curl, CMake, and CTest.
+if(CMAKE_USE_SYSTEM_ZLIB)
+ find_package(ZLIB)
+ if(NOT ZLIB_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_ZLIB is ON but a zlib is not found!")
+ endif()
+else()
+ if(NOT POLICY CMP0102) # CMake < 3.17
+ # Store in cache to protect from mark_as_advanced.
+ set(ZLIB_INCLUDE_DIR ${CMake_SOURCE_DIR}/Utilities CACHE PATH "")
+ else()
+ set(ZLIB_INCLUDE_DIR ${CMake_SOURCE_DIR}/Utilities)
+ endif()
+ set(ZLIB_LIBRARY cmzlib)
+ set(WITHOUT_ZLIB_DLL "")
+ set(WITHOUT_ZLIB_DLL_WITH_LIB cmzlib)
+ set(ZLIB_DLL "")
+ set(ZLIB_DLL_WITH_LIB cmzlib)
+ set(ZLIB_WINAPI "")
+ set(ZLIB_WINAPI_COMPILED 0)
+ set(ZLIB_WINAPI_WITH_LIB cmzlib)
+ add_subdirectory(Utilities/cmzlib)
+ add_library(ZLIB::ZLIB ALIAS cmzlib)
+ CMAKE_SET_TARGET_FOLDER(cmzlib "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Build Curl library for CTest.
+if(CMAKE_USE_SYSTEM_CURL)
+ find_package(CURL)
+ if(NOT CURL_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_CURL is ON but a curl is not found!")
+ endif()
+else()
+ if(CMAKE_TESTS_CDASH_SERVER)
+ set(CMAKE_CURL_TEST_URL "${CMAKE_TESTS_CDASH_SERVER}/user.php")
+ endif()
+ set(_CMAKE_USE_OPENSSL_DEFAULT OFF)
+ if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE
+ AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)")
+ set(_CMAKE_USE_OPENSSL_DEFAULT ON)
+ endif()
+ option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT})
+ mark_as_advanced(CMAKE_USE_OPENSSL)
+ if(CMAKE_USE_OPENSSL)
+ set(CURL_CA_BUNDLE "" CACHE FILEPATH "Path to SSL CA Certificate Bundle")
+ set(CURL_CA_PATH "" CACHE PATH "Path to SSL CA Certificate Directory")
+ mark_as_advanced(CURL_CA_BUNDLE CURL_CA_PATH)
+ endif()
+ if(NOT CMAKE_USE_SYSTEM_NGHTTP2)
+ # Tell curl's FindNGHTTP2 module to use our library.
+ set(NGHTTP2_LIBRARY cmnghttp2)
+ set(NGHTTP2_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmnghttp2/lib/includes)
+ endif()
+ add_subdirectory(Utilities/cmcurl)
+ add_library(CURL::libcurl ALIAS cmcurl)
+ CMAKE_SET_TARGET_FOLDER(cmcurl "Utilities/3rdParty")
+ CMAKE_SET_TARGET_FOLDER(LIBCURL "Utilities/3rdParty")
+ if(NOT CMAKE_USE_SYSTEM_NGHTTP2)
+ # Configure after curl to re-use some check results.
+ add_subdirectory(Utilities/cmnghttp2)
+ CMAKE_SET_TARGET_FOLDER(cmnghttp2 "Utilities/3rdParty")
+ endif()
+endif()
+
+#---------------------------------------------------------------------
+# Build expat library for CMake, CTest, and libarchive.
+if(CMAKE_USE_SYSTEM_EXPAT)
+ find_package(EXPAT)
+ if(NOT EXPAT_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_EXPAT is ON but a expat is not found!")
+ endif()
+ set(CMAKE_EXPAT_INCLUDES ${EXPAT_INCLUDE_DIRS})
+ set(CMAKE_EXPAT_LIBRARIES ${EXPAT_LIBRARIES})
+else()
+ set(CMAKE_EXPAT_INCLUDES)
+ set(CMAKE_EXPAT_LIBRARIES cmexpat)
+ add_subdirectory(Utilities/cmexpat)
+ add_library(EXPAT::EXPAT ALIAS cmexpat)
+ CMAKE_SET_TARGET_FOLDER(cmexpat "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Build or use system libbz2 for libarchive.
+if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
+ if(CMAKE_USE_SYSTEM_BZIP2)
+ find_package(BZip2)
+ else()
+ set(BZIP2_INCLUDE_DIR
+ "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmbzip2")
+ set(BZIP2_LIBRARIES cmbzip2)
+ set(BZIP2_NEED_PREFIX "")
+ set(USE_BZIP2_DLL "")
+ set(USE_BZIP2_DLL_WITH_LIB cmbzip2)
+ set(USE_BZIP2_STATIC "")
+ set(USE_BZIP2_STATIC_WITH_LIB cmbzip2)
+ add_subdirectory(Utilities/cmbzip2)
+ CMAKE_SET_TARGET_FOLDER(cmbzip2 "Utilities/3rdParty")
+ endif()
+endif()
+
+#---------------------------------------------------------------------
+# Build or use system zstd for libarchive.
+if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
+ if(NOT CMAKE_USE_SYSTEM_ZSTD)
+ set(ZSTD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmzstd")
+ set(ZSTD_LIBRARY cmzstd)
+ add_subdirectory(Utilities/cmzstd)
+ CMAKE_SET_TARGET_FOLDER(cmzstd "Utilities/3rdParty")
+ endif()
+endif()
+
+#---------------------------------------------------------------------
+# Build or use system liblzma for libarchive.
+if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE)
+ if(CMAKE_USE_SYSTEM_LIBLZMA)
+ find_package(LibLZMA)
+ if(NOT LIBLZMA_FOUND)
+ message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!")
+ endif()
+ else()
+ add_subdirectory(Utilities/cmliblzma)
+ CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty")
+ set(LIBLZMA_HAS_AUTO_DECODER 1)
+ set(LIBLZMA_HAS_EASY_ENCODER 1)
+ set(LIBLZMA_HAS_LZMA_PRESET 1)
+ set(LIBLZMA_INCLUDE_DIR
+ "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api")
+ set(LIBLZMA_LIBRARY cmliblzma)
+ set(HAVE_LZMA_STREAM_ENCODER_MT 1)
+ endif()
+endif()
+
+#---------------------------------------------------------------------
+# Build or use system libarchive for CMake and CTest.
+if(CMAKE_USE_SYSTEM_LIBARCHIVE)
+ find_package(LibArchive 3.3.3)
+ if(NOT LibArchive_FOUND)
+ message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBARCHIVE is ON but LibArchive is not found!")
+ endif()
+ # NOTE `FindLibArchive` got imported targets support since 3.17
+ if (NOT TARGET LibArchive::LibArchive)
+ add_library(LibArchive::LibArchive UNKNOWN IMPORTED)
+ set_target_properties(LibArchive::LibArchive PROPERTIES
+ IMPORTED_LOCATION "${LibArchive_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibArchive_INCLUDE_DIRS}")
+ endif ()
+else()
+ set(EXPAT_INCLUDE_DIR ${CMAKE_EXPAT_INCLUDES})
+ set(EXPAT_LIBRARY ${CMAKE_EXPAT_LIBRARIES})
+ set(ENABLE_MBEDTLS OFF)
+ set(ENABLE_NETTLE OFF)
+ if(DEFINED CMAKE_USE_OPENSSL)
+ set(ENABLE_OPENSSL "${CMAKE_USE_OPENSSL}")
+ else()
+ set(ENABLE_OPENSSL OFF)
+ endif()
+ set(ENABLE_LIBB2 OFF)
+ set(ENABLE_LZ4 OFF)
+ set(ENABLE_LZO OFF)
+ set(ENABLE_LZMA ON)
+ set(ENABLE_ZSTD ON)
+ set(ENABLE_ZLIB ON)
+ set(ENABLE_BZip2 ON)
+ set(ENABLE_LIBXML2 OFF)
+ set(ENABLE_EXPAT OFF)
+ set(ENABLE_PCREPOSIX OFF)
+ set(ENABLE_LibGCC OFF)
+ set(ENABLE_CNG OFF)
+ set(ENABLE_TAR OFF)
+ set(ENABLE_TAR_SHARED OFF)
+ set(ENABLE_CPIO OFF)
+ set(ENABLE_CPIO_SHARED OFF)
+ set(ENABLE_CAT OFF)
+ set(ENABLE_CAT_SHARED OFF)
+ set(ENABLE_XATTR OFF)
+ set(ENABLE_ACL OFF)
+ set(ENABLE_ICONV OFF)
+ set(ENABLE_TEST OFF)
+ set(ENABLE_COVERAGE OFF)
+ set(ENABLE_INSTALL OFF)
+ set(POSIX_REGEX_LIB "" CACHE INTERNAL "libarchive: No POSIX regular expression support")
+ set(ENABLE_SAFESEH "" CACHE INTERNAL "libarchive: No /SAFESEH linker flag")
+ set(WINDOWS_VERSION "WIN7" CACHE INTERNAL "libarchive: Set Windows version to use (Windows only)")
+ add_subdirectory(Utilities/cmlibarchive)
+ add_library(LibArchive::LibArchive ALIAS cmlibarchive)
+ target_compile_definitions(cmlibarchive INTERFACE LIBARCHIVE_STATIC)
+ CMAKE_SET_TARGET_FOLDER(cmlibarchive "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Build jsoncpp library.
+if(CMAKE_USE_SYSTEM_JSONCPP)
+ find_package(JsonCpp 1.6.0)
+ if(NOT JsonCpp_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_JSONCPP is ON but a JsonCpp is not found!")
+ endif()
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang")
+ set_property(TARGET JsonCpp::JsonCpp APPEND PROPERTY
+ INTERFACE_COMPILE_OPTIONS -Wno-deprecated-declarations)
+ endif()
+else()
+ add_subdirectory(Utilities/cmjsoncpp)
+ add_library(JsonCpp::JsonCpp ALIAS cmjsoncpp)
+ CMAKE_SET_TARGET_FOLDER(cmjsoncpp "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Build libuv library.
+if(CMAKE_USE_SYSTEM_LIBUV)
+ if(WIN32)
+ find_package(LibUV 1.38.0)
+ else()
+ find_package(LibUV 1.28.0)
+ endif()
+ if(NOT LIBUV_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!")
+ endif()
+else()
+ add_subdirectory(Utilities/cmlibuv)
+ add_library(LibUV::LibUV ALIAS cmlibuv)
+ CMAKE_SET_TARGET_FOLDER(cmlibuv "Utilities/3rdParty")
+endif()
+
+#---------------------------------------------------------------------
+# Use curses?
+if(NOT DEFINED BUILD_CursesDialog)
+ if(UNIX)
+ include(${CMake_SOURCE_DIR}/Source/Checks/Curses.cmake)
+ set(BUILD_CursesDialog_DEFAULT "${CMakeCheckCurses_COMPILED}")
+ elseif(WIN32)
+ set(BUILD_CursesDialog_DEFAULT "OFF")
+ endif()
+ option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" "${BUILD_CursesDialog_DEFAULT}")
+endif()
+if(BUILD_CursesDialog)
+ if(UNIX)
+ set(CURSES_NEED_NCURSES TRUE)
+ find_package(Curses)
+ if(NOT CURSES_FOUND)
+ message(WARNING
+ "'ccmake' will not be built because Curses was not found.\n"
+ "Turn off BUILD_CursesDialog to suppress this message."
+ )
+ set(BUILD_CursesDialog 0)
+ endif()
+ elseif(WIN32)
+ # FIXME: Add support for system-provided pdcurses.
+ add_subdirectory(Utilities/cmpdcurses)
+ set(CURSES_LIBRARY cmpdcurses)
+ set(CURSES_INCLUDE_PATH "") # cmpdcurses has usage requirements
+ set(CMAKE_USE_SYSTEM_FORM 0)
+ set(HAVE_CURSES_USE_DEFAULT_COLORS 1)
+ endif()
+endif()
+if(BUILD_CursesDialog)
+ if(NOT CMAKE_USE_SYSTEM_FORM)
+ add_subdirectory(Source/CursesDialog/form)
+ elseif(NOT CURSES_FORM_LIBRARY)
+ message(FATAL_ERROR "CMAKE_USE_SYSTEM_FORM in ON but CURSES_FORM_LIBRARY is not set!")
+ endif()
+endif()
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 0c263bb75..c90b7ee72 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -3,7 +3,7 @@
project(QtDialog)
CMake_OPTIONAL_COMPONENT(cmake-gui)
-set (QT_COMPONENTS
+set(QT_COMPONENTS
Core
Widgets
Gui
@@ -41,8 +41,8 @@ set(CMake_QT_EXTRA_LIBRARIES)
# Try to find the package WinExtras for the task bar progress
if(WIN32)
find_package(Qt${INSTALLED_QT_VERSION}WinExtras QUIET)
- if (Qt${INSTALLED_QT_VERSION}WinExtras_FOUND)
- add_definitions(-DQT_WINEXTRAS)
+ if(Qt${INSTALLED_QT_VERSION}WinExtras_FOUND)
+ add_compile_definitions(QT_WINEXTRAS)
list(APPEND CMake_QT_EXTRA_LIBRARIES Qt${INSTALLED_QT_VERSION}::WinExtras)
list(APPEND QT_COMPONENTS WinExtras)
endif()
@@ -100,14 +100,14 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
endif()
endmacro()
macro(install_qt_plugins _comps _plugins_var)
- foreach(_qt_comp ${${_comps}})
- if (INSTALLED_QT_VERSION VERSION_LESS 6)
+ foreach(_qt_comp IN LISTS ${_comps})
+ if(INSTALLED_QT_VERSION VERSION_LESS 6)
set(_qt_module_plugins ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_PLUGINS})
else()
get_target_property(_qt_module_plugins Qt${INSTALLED_QT_VERSION}::${_qt_comp} QT_PLUGINS)
endif()
- foreach(_qt_plugin ${_qt_module_plugins})
- if (INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6)
+ foreach(_qt_plugin IN LISTS _qt_module_plugins)
+ if(INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6)
# Qt6 provides the plugins as individual packages that need to be found.
find_package(Qt${INSTALLED_QT_VERSION}${_qt_plugin} QUIET
PATHS ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_DIR})
@@ -117,7 +117,7 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
endforeach()
endmacro()
if(APPLE)
- if (INSTALLED_QT_VERSION VERSION_EQUAL 5)
+ if(INSTALLED_QT_VERSION VERSION_EQUAL 5)
install_qt_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
if(TARGET Qt5::QMacStylePlugin)
install_qt_plugin("Qt5::QMacStylePlugin" QT_PLUGINS)
@@ -132,7 +132,7 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
${COMPONENT})
elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
- if (INSTALLED_QT_VERSION VERSION_EQUAL 5)
+ if(INSTALLED_QT_VERSION VERSION_EQUAL 5)
install_qt_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
else()
# FIXME: Minimize plugins for Qt6.
@@ -152,7 +152,10 @@ if(APPLE)
get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
endif()
-set(SRCS
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_library(
+ CMakeGUILib STATIC
AddCacheEntry.cxx
AddCacheEntry.h
CMakeSetupDialog.cxx
@@ -179,6 +182,16 @@ set(SRCS
WarningMessagesDialog.cxx
WarningMessagesDialog.h
)
+# CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line
+target_link_libraries(
+ CMakeGUILib
+ PUBLIC
+ CMakeLib
+ ${CMake_QT_EXTRA_LIBRARIES}
+ Qt${INSTALLED_QT_VERSION}::Core
+ Qt${INSTALLED_QT_VERSION}::Widgets
+ )
+
set(UI_SRCS
CMakeSetupDialog.ui
Compilers.ui
@@ -204,7 +217,7 @@ set(MOC_SRCS
)
set(QRC_SRCS CMakeSetup.qrc)
-if (INSTALLED_QT_VERSION VERSION_LESS 6)
+if(INSTALLED_QT_VERSION VERSION_LESS 6)
qt5_wrap_ui(UI_BUILT_SRCS ${UI_SRCS})
qt5_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS})
qt5_add_resources(QRC_BUILT_SRCS ${QRC_SRCS})
@@ -215,15 +228,18 @@ else()
endif()
add_library(CMakeGUIQRCLib OBJECT ${QRC_BUILT_SRCS})
-if (FALSE) # CMake's bootstrap binary does not support automoc
+if(FALSE) # CMake's bootstrap binary does not support automoc
set(CMAKE_AUTOMOC 1)
set(CMAKE_AUTORCC 1)
set(CMAKE_AUTOUIC 1)
-else ()
- list(APPEND SRCS
- ${UI_BUILT_SRCS}
- ${MOC_BUILT_SRCS})
-endif ()
+else()
+ target_sources(
+ CMakeGUILib
+ PRIVATE
+ ${UI_BUILT_SRCS}
+ ${MOC_BUILT_SRCS}
+ )
+endif()
if(USE_LGPL)
install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv${USE_LGPL}.txt
@@ -233,22 +249,25 @@ if(USE_LGPL)
PROPERTY COMPILE_DEFINITIONS USE_LGPL="${USE_LGPL}")
endif()
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-add_library(CMakeGUILib STATIC ${SRCS})
-# CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line
-target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES}
- Qt${INSTALLED_QT_VERSION}::Core Qt${INSTALLED_QT_VERSION}::Widgets)
-
add_library(CMakeGUIMainLib STATIC CMakeSetup.cxx)
-target_link_libraries(CMakeGUIMainLib PUBLIC CMakeGUILib)
+target_link_libraries(
+ CMakeGUIMainLib
+ PUBLIC
+ CMakeGUILib
+ )
-add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx ${MANIFEST_FILE})
-target_link_libraries(cmake-gui CMakeGUIMainLib Qt${INSTALLED_QT_VERSION}::Core)
+add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx)
+target_link_libraries(cmake-gui
+ PRIVATE
+ CMakeGUIMainLib
+ CMakeGUIQRCLib
+ $<TARGET_NAME_IF_EXISTS:CMakeVersion>
+ ManifestLib
+ Qt${INSTALLED_QT_VERSION}::Core
+ )
-target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeGUIQRCLib>)
if(WIN32)
- target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeVersion> CMakeSetup.rc)
+ target_sources(CMakeGUIMainLib INTERFACE CMakeSetup.rc)
endif()
if(APPLE)
target_sources(CMakeGUIMainLib INTERFACE CMakeSetup.icns)
@@ -300,21 +319,19 @@ if(APPLE)
$<TARGET_FILE_DIR:cmake>/cmake-gui
)
endif()
-set(CMAKE_INSTALL_DESTINATION_ARGS
- BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT})
install(TARGETS cmake-gui
RUNTIME DESTINATION bin ${COMPONENT}
- ${CMAKE_INSTALL_DESTINATION_ARGS})
+ BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT})
if(UNIX AND NOT APPLE)
- foreach (size IN ITEMS 32 128)
+ foreach(size IN ITEMS 32 128)
install(
FILES "${CMAKE_CURRENT_SOURCE_DIR}/CMakeSetup${size}.png"
DESTINATION "${CMAKE_XDGDATA_DIR}/icons/hicolor/${size}x${size}/apps"
${COMPONENT}
RENAME "CMakeSetup.png")
- endforeach ()
+ endforeach()
# install a desktop file so CMake appears in the application start menu
# with an icon
@@ -348,5 +365,4 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
endif()
set(CMAKE_PACKAGE_QTGUI TRUE)
-configure_file("${QtDialog_SOURCE_DIR}/QtDialogCPack.cmake.in"
- "${QtDialog_BINARY_DIR}/QtDialogCPack.cmake" @ONLY)
+configure_file(QtDialogCPack.cmake.in QtDialogCPack.cmake @ONLY)
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index f3c4a8be5..707eaae2a 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -244,7 +244,8 @@ void StartCompilerSetup::onGeneratorChanged(int index)
if (!DefaultGeneratorPlatform.isEmpty()) {
int platform_index = platforms.indexOf(DefaultGeneratorPlatform);
if (platform_index != -1) {
- this->PlatformOptions->setCurrentIndex(platform_index);
+ // The index is off-by-one due to the first empty item added above.
+ this->PlatformOptions->setCurrentIndex(platform_index + 1);
}
}
} else {
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 83d630600..6a2ab0bfc 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -26,6 +26,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
std::string binArg;
bool excludeFromAll = false;
+ bool system = false;
// process the rest of the arguments looking for optional args
for (std::string const& arg : cmMakeRange(args).advance(1)) {
@@ -33,6 +34,10 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
excludeFromAll = true;
continue;
}
+ if (arg == "SYSTEM") {
+ system = true;
+ continue;
+ }
if (binArg.empty()) {
binArg = arg;
} else {
@@ -40,6 +45,11 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
return false;
}
}
+ // "SYSTEM" directory property should also affects targets in nested
+ // subdirectories.
+ if (mf.GetPropertyAsBool("SYSTEM")) {
+ system = true;
+ }
// Compute the full path to the specified source directory.
// Interpret a relative path with respect to the current source directory.
@@ -102,7 +112,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
binPath = cmSystemTools::CollapseFullPath(binPath);
// Add the subdirectory using the computed full paths.
- mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true);
+ mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true, system);
return true;
}
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index 4624f1c0a..ad57a88a5 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -4,9 +4,14 @@
#include <algorithm>
+#include "cmArgumentParserTypes.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+
namespace ArgumentParser {
-auto ActionMap::Emplace(cm::string_view name, Action action)
+auto KeywordActionMap::Emplace(cm::string_view name, KeywordAction action)
-> std::pair<iterator, bool>
{
auto const it =
@@ -19,7 +24,7 @@ auto ActionMap::Emplace(cm::string_view name, Action action)
: std::make_pair(this->emplace(it, name, std::move(action)), true);
}
-auto ActionMap::Find(cm::string_view name) const -> const_iterator
+auto KeywordActionMap::Find(cm::string_view name) const -> const_iterator
{
auto const it =
std::lower_bound(this->begin(), this->end(), name,
@@ -29,68 +34,171 @@ auto ActionMap::Find(cm::string_view name) const -> const_iterator
return (it != this->end() && it->first == name) ? it : this->end();
}
+auto PositionActionMap::Emplace(std::size_t pos, PositionAction action)
+ -> std::pair<iterator, bool>
+{
+ auto const it = std::lower_bound(
+ this->begin(), this->end(), pos,
+ [](value_type const& elem, std::size_t k) { return elem.first < k; });
+ return (it != this->end() && it->first == pos)
+ ? std::make_pair(it, false)
+ : std::make_pair(this->emplace(it, pos, std::move(action)), true);
+}
+
+auto PositionActionMap::Find(std::size_t pos) const -> const_iterator
+{
+ auto const it = std::lower_bound(
+ this->begin(), this->end(), pos,
+ [](value_type const& elem, std::size_t k) { return elem.first < k; });
+ return (it != this->end() && it->first == pos) ? it : this->end();
+}
+
+void Instance::Bind(std::function<Continue(cm::string_view)> f,
+ ExpectAtLeast expect)
+{
+ this->KeywordValueFunc = std::move(f);
+ this->KeywordValuesExpected = expect.Count;
+}
+
void Instance::Bind(bool& val)
{
val = true;
- this->CurrentString = nullptr;
- this->CurrentList = nullptr;
- this->ExpectValue = false;
+ this->Bind(nullptr, ExpectAtLeast{ 0 });
}
void Instance::Bind(std::string& val)
{
- this->CurrentString = &val;
- this->CurrentList = nullptr;
- this->ExpectValue = true;
+ this->Bind(
+ [&val](cm::string_view arg) -> Continue {
+ val = std::string(arg);
+ return Continue::No;
+ },
+ ExpectAtLeast{ 1 });
+}
+
+void Instance::Bind(NonEmpty<std::string>& val)
+{
+ this->Bind(
+ [this, &val](cm::string_view arg) -> Continue {
+ if (arg.empty() && this->ParseResults) {
+ this->ParseResults->AddKeywordError(this->Keyword,
+ " empty string not allowed\n");
+ }
+ val.assign(std::string(arg));
+ return Continue::No;
+ },
+ ExpectAtLeast{ 1 });
}
-void Instance::Bind(StringList& val)
+void Instance::Bind(Maybe<std::string>& val)
{
- this->CurrentString = nullptr;
- this->CurrentList = &val;
- this->ExpectValue = true;
+ this->Bind(
+ [&val](cm::string_view arg) -> Continue {
+ static_cast<std::string&>(val) = std::string(arg);
+ return Continue::No;
+ },
+ ExpectAtLeast{ 0 });
}
-void Instance::Bind(MultiStringList& val)
+void Instance::Bind(MaybeEmpty<std::vector<std::string>>& val)
{
- this->CurrentString = nullptr;
- this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back());
- this->ExpectValue = false;
+ this->Bind(
+ [&val](cm::string_view arg) -> Continue {
+ val.emplace_back(arg);
+ return Continue::Yes;
+ },
+ ExpectAtLeast{ 0 });
}
-void Instance::Consume(cm::string_view arg, void* result,
- std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords)
+void Instance::Bind(NonEmpty<std::vector<std::string>>& val)
{
- auto const it = this->Bindings.Find(arg);
- if (it != this->Bindings.end()) {
- if (parsedKeywords != nullptr) {
- parsedKeywords->emplace_back(arg);
+ this->Bind(
+ [&val](cm::string_view arg) -> Continue {
+ val.emplace_back(arg);
+ return Continue::Yes;
+ },
+ ExpectAtLeast{ 1 });
+}
+
+void Instance::Bind(std::vector<std::vector<std::string>>& multiVal)
+{
+ multiVal.emplace_back();
+ std::vector<std::string>& val = multiVal.back();
+ this->Bind(
+ [&val](cm::string_view arg) -> Continue {
+ val.emplace_back(arg);
+ return Continue::Yes;
+ },
+ ExpectAtLeast{ 0 });
+}
+
+void Instance::Consume(std::size_t pos, cm::string_view arg)
+{
+ auto const it = this->Bindings.Keywords.Find(arg);
+ if (it != this->Bindings.Keywords.end()) {
+ this->FinishKeyword();
+ this->Keyword = it->first;
+ this->KeywordValuesSeen = 0;
+ this->DoneWithPositional = true;
+ if (this->Bindings.ParsedKeyword) {
+ this->Bindings.ParsedKeyword(*this, it->first);
}
- it->second(*this, result);
- if (this->ExpectValue && keywordsMissingValue != nullptr) {
- keywordsMissingValue->emplace_back(arg);
+ it->second(*this);
+ return;
+ }
+
+ if (this->KeywordValueFunc) {
+ switch (this->KeywordValueFunc(arg)) {
+ case Continue::Yes:
+ break;
+ case Continue::No:
+ this->KeywordValueFunc = nullptr;
+ break;
}
+ ++this->KeywordValuesSeen;
return;
}
- if (this->CurrentString != nullptr) {
- this->CurrentString->assign(std::string(arg));
- this->CurrentString = nullptr;
- this->CurrentList = nullptr;
- } else if (this->CurrentList != nullptr) {
- this->CurrentList->emplace_back(arg);
- } else if (unparsedArguments != nullptr) {
- unparsedArguments->emplace_back(arg);
+ if (!this->DoneWithPositional) {
+ auto const pit = this->Bindings.Positions.Find(pos);
+ if (pit != this->Bindings.Positions.end()) {
+ pit->second(*this, pos, arg);
+ return;
+ }
+ }
+
+ if (this->UnparsedArguments != nullptr) {
+ this->UnparsedArguments->emplace_back(arg);
}
+}
- if (this->ExpectValue) {
- if (keywordsMissingValue != nullptr) {
- keywordsMissingValue->pop_back();
+void Instance::FinishKeyword()
+{
+ if (this->Keyword.empty()) {
+ return;
+ }
+ if (this->KeywordValuesSeen < this->KeywordValuesExpected) {
+ if (this->ParseResults != nullptr) {
+ this->ParseResults->AddKeywordError(this->Keyword,
+ " missing required value\n");
}
- this->ExpectValue = false;
+ if (this->Bindings.KeywordMissingValue) {
+ this->Bindings.KeywordMissingValue(*this, this->Keyword);
+ }
+ }
+}
+
+bool ParseResult::MaybeReportError(cmMakefile& mf) const
+{
+ if (*this) {
+ return false;
+ }
+ std::string e;
+ for (auto const& ke : this->KeywordErrors) {
+ e = cmStrCat(e, "Error after keyword \"", ke.first, "\":\n", ke.second);
}
+ mf.IssueMessage(MessageType::FATAL_ERROR, e);
+ return true;
}
} // namespace ArgumentParser
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index 71ed84481..fdf54fbd4 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -5,59 +5,220 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <cassert>
+#include <cstddef>
#include <functional>
+#include <map>
#include <string>
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
+#include <cm/type_traits>
#include <cmext/string_view>
+#include "cmArgumentParserTypes.h" // IWYU pragma: keep
+
+template <typename Result>
+class cmArgumentParser; // IWYU pragma: keep
+
+class cmMakefile;
+
namespace ArgumentParser {
-using StringList = std::vector<std::string>;
-using MultiStringList = std::vector<StringList>;
+class ParseResult
+{
+ std::map<cm::string_view, std::string> KeywordErrors;
+
+public:
+ explicit operator bool() const { return this->KeywordErrors.empty(); }
+
+ void AddKeywordError(cm::string_view key, cm::string_view text)
+
+ {
+ this->KeywordErrors[key] += text;
+ }
+
+ std::map<cm::string_view, std::string> const& GetKeywordErrors() const
+ {
+ return this->KeywordErrors;
+ }
+
+ bool MaybeReportError(cmMakefile& mf) const;
+};
+
+template <typename Result>
+typename std::enable_if<std::is_base_of<ParseResult, Result>::value,
+ ParseResult*>::type
+AsParseResultPtr(Result& result)
+{
+ return &result;
+}
+
+template <typename Result>
+typename std::enable_if<!std::is_base_of<ParseResult, Result>::value,
+ ParseResult*>::type
+AsParseResultPtr(Result&)
+{
+ return nullptr;
+}
+
+enum class Continue
+{
+ No,
+ Yes,
+};
+
+struct ExpectAtLeast
+{
+ std::size_t Count = 0;
+
+ ExpectAtLeast(std::size_t count)
+ : Count(count)
+ {
+ }
+};
class Instance;
-using Action = std::function<void(Instance&, void*)>;
+using KeywordAction = std::function<void(Instance&)>;
+using KeywordNameAction = std::function<void(Instance&, cm::string_view)>;
+using PositionAction =
+ std::function<void(Instance&, std::size_t, cm::string_view)>;
-// using ActionMap = cm::flat_map<cm::string_view, Action>;
-class ActionMap : public std::vector<std::pair<cm::string_view, Action>>
+// using KeywordActionMap = cm::flat_map<cm::string_view, KeywordAction>;
+class KeywordActionMap
+ : public std::vector<std::pair<cm::string_view, KeywordAction>>
{
public:
- std::pair<iterator, bool> Emplace(cm::string_view name, Action action);
+ std::pair<iterator, bool> Emplace(cm::string_view name,
+ KeywordAction action);
const_iterator Find(cm::string_view name) const;
};
+// using PositionActionMap = cm::flat_map<cm::string_view, PositionAction>;
+class PositionActionMap
+ : public std::vector<std::pair<std::size_t, PositionAction>>
+{
+public:
+ std::pair<iterator, bool> Emplace(std::size_t pos, PositionAction action);
+ const_iterator Find(std::size_t pos) const;
+};
+
+class ActionMap
+{
+public:
+ KeywordActionMap Keywords;
+ KeywordNameAction KeywordMissingValue;
+ KeywordNameAction ParsedKeyword;
+ PositionActionMap Positions;
+};
+
+class Base
+{
+public:
+ using ExpectAtLeast = ArgumentParser::ExpectAtLeast;
+ using Continue = ArgumentParser::Continue;
+ using Instance = ArgumentParser::Instance;
+ using ParseResult = ArgumentParser::ParseResult;
+
+ ArgumentParser::ActionMap Bindings;
+
+ bool MaybeBind(cm::string_view name, KeywordAction action)
+ {
+ return this->Bindings.Keywords.Emplace(name, std::move(action)).second;
+ }
+
+ void Bind(cm::string_view name, KeywordAction action)
+ {
+ bool const inserted = this->MaybeBind(name, std::move(action));
+ assert(inserted);
+ static_cast<void>(inserted);
+ }
+
+ void BindParsedKeyword(KeywordNameAction action)
+ {
+ assert(!this->Bindings.ParsedKeyword);
+ this->Bindings.ParsedKeyword = std::move(action);
+ }
+
+ void BindKeywordMissingValue(KeywordNameAction action)
+ {
+ assert(!this->Bindings.KeywordMissingValue);
+ this->Bindings.KeywordMissingValue = std::move(action);
+ }
+
+ void Bind(std::size_t pos, PositionAction action)
+ {
+ bool const inserted =
+ this->Bindings.Positions.Emplace(pos, std::move(action)).second;
+ assert(inserted);
+ static_cast<void>(inserted);
+ }
+};
+
class Instance
{
public:
- Instance(ActionMap const& bindings)
+ Instance(ActionMap const& bindings, ParseResult* parseResult,
+ std::vector<std::string>* unparsedArguments, void* result = nullptr)
: Bindings(bindings)
+ , ParseResults(parseResult)
+ , UnparsedArguments(unparsedArguments)
+ , Result(result)
{
}
+ void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect);
void Bind(bool& val);
void Bind(std::string& val);
- void Bind(StringList& val);
- void Bind(MultiStringList& val);
+ void Bind(NonEmpty<std::string>& val);
+ void Bind(Maybe<std::string>& val);
+ void Bind(MaybeEmpty<std::vector<std::string>>& val);
+ void Bind(NonEmpty<std::vector<std::string>>& val);
+ void Bind(std::vector<std::vector<std::string>>& val);
+
+ // cm::optional<> records the presence the keyword to which it binds.
+ template <typename T>
+ void Bind(cm::optional<T>& optVal)
+ {
+ if (!optVal) {
+ optVal.emplace();
+ }
+ this->Bind(*optVal);
+ }
- void Consume(cm::string_view arg, void* result,
- std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords);
+ template <typename Range>
+ void Parse(Range const& args, std::size_t pos = 0)
+ {
+ for (cm::string_view arg : args) {
+ this->Consume(pos++, arg);
+ }
+ this->FinishKeyword();
+ }
private:
ActionMap const& Bindings;
- std::string* CurrentString = nullptr;
- StringList* CurrentList = nullptr;
- bool ExpectValue = false;
+ ParseResult* ParseResults = nullptr;
+ std::vector<std::string>* UnparsedArguments = nullptr;
+ void* Result = nullptr;
+
+ cm::string_view Keyword;
+ std::size_t KeywordValuesSeen = 0;
+ std::size_t KeywordValuesExpected = 0;
+ std::function<Continue(cm::string_view)> KeywordValueFunc;
+ bool DoneWithPositional = false;
+
+ void Consume(std::size_t pos, cm::string_view arg);
+ void FinishKeyword();
+
+ template <typename Result>
+ friend class ::cmArgumentParser;
};
} // namespace ArgumentParser
template <typename Result>
-class cmArgumentParser
+class cmArgumentParser : private ArgumentParser::Base
{
public:
// I *think* this function could be made `constexpr` when the code is
@@ -65,83 +226,194 @@ public:
template <typename T>
cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
{
- bool const inserted =
- this->Bindings
- .Emplace(name,
- [member](ArgumentParser::Instance& instance, void* result) {
- instance.Bind(static_cast<Result*>(result)->*member);
- })
- .second;
- assert(inserted), (void)inserted;
+ this->Base::Bind(name, [member](Instance& instance) {
+ instance.Bind(static_cast<Result*>(instance.Result)->*member);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(cm::static_string_view name,
+ Continue (Result::*member)(cm::string_view),
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [member, expect](Instance& instance) {
+ Result* result = static_cast<Result*>(instance.Result);
+ instance.Bind(
+ [result, member](cm::string_view arg) -> Continue {
+ return (result->*member)(arg);
+ },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(cm::static_string_view name,
+ Continue (Result::*member)(cm::string_view,
+ cm::string_view),
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [member, expect](Instance& instance) {
+ Result* result = static_cast<Result*>(instance.Result);
+ cm::string_view keyword = instance.Keyword;
+ instance.Bind(
+ [result, member, keyword](cm::string_view arg) -> Continue {
+ return (result->*member)(keyword, arg);
+ },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(cm::static_string_view name,
+ std::function<Continue(Result&, cm::string_view)> f,
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [f, expect](Instance& instance) {
+ Result* result = static_cast<Result*>(instance.Result);
+ instance.Bind(
+ [result, &f](cm::string_view arg) -> Continue {
+ return f(*result, arg);
+ },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(
+ cm::static_string_view name,
+ std::function<Continue(Result&, cm::string_view, cm::string_view)> f,
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [f, expect](Instance& instance) {
+ Result* result = static_cast<Result*>(instance.Result);
+ cm::string_view keyword = instance.Keyword;
+ instance.Bind(
+ [result, keyword, &f](cm::string_view arg) -> Continue {
+ return f(*result, keyword, arg);
+ },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(std::size_t position,
+ cm::optional<std::string> Result::*member)
+ {
+ this->Base::Bind(
+ position,
+ [member](Instance& instance, std::size_t, cm::string_view arg) {
+ Result* result = static_cast<Result*>(instance.Result);
+ result->*member = arg;
+ });
+ return *this;
+ }
+
+ cmArgumentParser& BindParsedKeywords(
+ std::vector<cm::string_view> Result::*member)
+ {
+ this->Base::BindParsedKeyword(
+ [member](Instance& instance, cm::string_view arg) {
+ (static_cast<Result*>(instance.Result)->*member).emplace_back(arg);
+ });
return *this;
}
template <typename Range>
- void Parse(Result& result, Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ bool Parse(Result& result, Range const& args,
+ std::vector<std::string>* unparsedArguments,
+ std::size_t pos = 0) const
{
- ArgumentParser::Instance instance(this->Bindings);
- for (cm::string_view arg : args) {
- instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue,
- parsedKeywords);
- }
+ using ArgumentParser::AsParseResultPtr;
+ ParseResult* parseResultPtr = AsParseResultPtr(result);
+ Instance instance(this->Bindings, parseResultPtr, unparsedArguments,
+ &result);
+ instance.Parse(args, pos);
+ return parseResultPtr ? static_cast<bool>(*parseResultPtr) : true;
}
template <typename Range>
- Result Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ Result Parse(Range const& args, std::vector<std::string>* unparsedArguments,
+ std::size_t pos = 0) const
{
Result result;
- this->Parse(result, args, unparsedArguments, keywordsMissingValue,
- parsedKeywords);
+ this->Parse(result, args, unparsedArguments, pos);
return result;
}
-
-private:
- ArgumentParser::ActionMap Bindings;
};
template <>
-class cmArgumentParser<void>
+class cmArgumentParser<void> : private ArgumentParser::Base
{
public:
template <typename T>
cmArgumentParser& Bind(cm::static_string_view name, T& ref)
{
- bool const inserted = this->Bind(cm::string_view(name), ref);
- assert(inserted), (void)inserted;
+ this->Base::Bind(name, [&ref](Instance& instance) { instance.Bind(ref); });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(cm::static_string_view name,
+ std::function<Continue(cm::string_view)> f,
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [f, expect](Instance& instance) {
+ instance.Bind([&f](cm::string_view arg) -> Continue { return f(arg); },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(
+ cm::static_string_view name,
+ std::function<Continue(cm::string_view, cm::string_view)> f,
+ ExpectAtLeast expect = { 1 })
+ {
+ this->Base::Bind(name, [f, expect](Instance& instance) {
+ cm::string_view keyword = instance.Keyword;
+ instance.Bind(
+ [keyword, &f](cm::string_view arg) -> Continue {
+ return f(keyword, arg);
+ },
+ expect);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& Bind(std::size_t position, cm::optional<std::string>& ref)
+ {
+ this->Base::Bind(position,
+ [&ref](Instance&, std::size_t, cm::string_view arg) {
+ ref = std::string(arg);
+ });
+ return *this;
+ }
+
+ cmArgumentParser& BindParsedKeywords(std::vector<cm::string_view>& ref)
+ {
+ this->Base::BindParsedKeyword(
+ [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
return *this;
}
template <typename Range>
- void Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ ParseResult Parse(Range const& args,
+ std::vector<std::string>* unparsedArguments,
+ std::size_t pos = 0) const
{
- ArgumentParser::Instance instance(this->Bindings);
- for (cm::string_view arg : args) {
- instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue,
- parsedKeywords);
- }
+ ParseResult parseResult;
+ Instance instance(this->Bindings, &parseResult, unparsedArguments);
+ instance.Parse(args, pos);
+ return parseResult;
}
protected:
+ using Base::Instance;
+ using Base::BindKeywordMissingValue;
+
template <typename T>
bool Bind(cm::string_view name, T& ref)
{
- return this->Bindings
- .Emplace(name,
- [&ref](ArgumentParser::Instance& instance, void*) {
- instance.Bind(ref);
- })
- .second;
+ return this->MaybeBind(name,
+ [&ref](Instance& instance) { instance.Bind(ref); });
}
-
-private:
- ArgumentParser::ActionMap Bindings;
};
diff --git a/Source/cmArgumentParserTypes.h b/Source/cmArgumentParserTypes.h
new file mode 100644
index 000000000..7daae0974
--- /dev/null
+++ b/Source/cmArgumentParserTypes.h
@@ -0,0 +1,69 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#if defined(__SUNPRO_CC)
+
+# include <string>
+# include <vector>
+
+namespace ArgumentParser {
+
+template <typename T>
+struct Maybe;
+template <>
+struct Maybe<std::string> : public std::string
+{
+ using std::string::basic_string;
+};
+
+template <typename T>
+struct MaybeEmpty;
+template <typename T>
+struct MaybeEmpty<std::vector<T>> : public std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template <typename T>
+struct NonEmpty;
+template <typename T>
+struct NonEmpty<std::vector<T>> : public std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+template <>
+struct NonEmpty<std::string> : public std::string
+{
+ using std::string::basic_string;
+};
+
+} // namespace ArgumentParser
+
+#else
+
+namespace ArgumentParser {
+
+template <typename T>
+struct Maybe : public T
+{
+ using T::T;
+};
+
+template <typename T>
+struct MaybeEmpty : public T
+{
+ using T::T;
+};
+
+template <typename T>
+struct NonEmpty : public T
+{
+ using T::T;
+};
+
+} // namespace ArgumentParser
+
+#endif
diff --git a/Source/cmBlockCommand.cxx b/Source/cmBlockCommand.cxx
new file mode 100644
index 000000000..ec7914906
--- /dev/null
+++ b/Source/cmBlockCommand.cxx
@@ -0,0 +1,197 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBlockCommand.h"
+
+#include <cstdint> // IWYU pragma: keep
+#include <utility>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/enum_set>
+#include <cmext/string_view>
+
+#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmExecutionStatus.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+namespace {
+enum class ScopeType : std::uint8_t
+{
+ VARIABLES,
+ POLICIES
+};
+using ScopeSet = cm::enum_set<ScopeType>;
+
+class BlockScopePushPop
+{
+public:
+ BlockScopePushPop(cmMakefile* m, const ScopeSet& scopes);
+ ~BlockScopePushPop() = default;
+
+ BlockScopePushPop(const BlockScopePushPop&) = delete;
+ BlockScopePushPop& operator=(const BlockScopePushPop&) = delete;
+
+private:
+ std::unique_ptr<cmMakefile::PolicyPushPop> PolicyScope;
+ std::unique_ptr<cmMakefile::VariablePushPop> VariableScope;
+};
+
+BlockScopePushPop::BlockScopePushPop(cmMakefile* mf, const ScopeSet& scopes)
+{
+ if (scopes.contains(ScopeType::POLICIES)) {
+ this->PolicyScope = cm::make_unique<cmMakefile::PolicyPushPop>(mf);
+ }
+ if (scopes.contains(ScopeType::VARIABLES)) {
+ this->VariableScope = cm::make_unique<cmMakefile::VariablePushPop>(mf);
+ }
+}
+
+class cmBlockFunctionBlocker : public cmFunctionBlocker
+{
+public:
+ cmBlockFunctionBlocker(cmMakefile* mf, const ScopeSet& scopes,
+ std::vector<std::string> variableNames);
+ ~cmBlockFunctionBlocker() override;
+
+ cm::string_view StartCommandName() const override { return "block"_s; }
+ cm::string_view EndCommandName() const override { return "endblock"_s; }
+
+ bool EndCommandSupportsArguments() const override { return false; }
+
+ bool ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus) override;
+
+private:
+ cmMakefile* Makefile;
+ ScopeSet Scopes;
+ BlockScopePushPop BlockScope;
+ std::vector<std::string> VariableNames;
+};
+
+cmBlockFunctionBlocker::cmBlockFunctionBlocker(
+ cmMakefile* const mf, const ScopeSet& scopes,
+ std::vector<std::string> variableNames)
+ : Makefile{ mf }
+ , Scopes{ scopes }
+ , BlockScope{ mf, scopes }
+ , VariableNames{ std::move(variableNames) }
+{
+}
+
+cmBlockFunctionBlocker::~cmBlockFunctionBlocker()
+{
+ if (this->Scopes.contains(ScopeType::VARIABLES)) {
+ this->Makefile->RaiseScope(this->VariableNames);
+ }
+}
+
+bool cmBlockFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile&) const
+{
+ // no arguments expected for endblock()
+ // but this method should not be called because EndCommandHasArguments()
+ // returns false.
+ return lff.Arguments().empty();
+}
+
+bool cmBlockFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus)
+{
+ auto& mf = inStatus.GetMakefile();
+
+ // Invoke all the functions that were collected in the block.
+ for (cmListFileFunction const& fn : functions) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(fn, status);
+ if (status.GetReturnInvoked()) {
+ mf.RaiseScope(status.GetReturnVariables());
+ inStatus.SetReturnInvoked(status.GetReturnVariables());
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ inStatus.SetBreakInvoked();
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ inStatus.SetContinueInvoked();
+ return true;
+ }
+ if (cmSystemTools::GetFatalErrorOccurred()) {
+ return true;
+ }
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+bool cmBlockCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ struct Arguments : public ArgumentParser::ParseResult
+ {
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> ScopeFor;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Propagate;
+ };
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("SCOPE_FOR"_s, &Arguments::ScopeFor)
+ .Bind("PROPAGATE"_s, &Arguments::Propagate);
+ std::vector<std::string> unrecognizedArguments;
+ auto parsedArgs = parser.Parse(args, &unrecognizedArguments);
+
+ if (!unrecognizedArguments.empty()) {
+ status.SetError(cmStrCat("called with unsupported argument \"",
+ unrecognizedArguments[0], '"'));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
+ cmSystemTools::SetFatalErrorOccurred();
+ return true;
+ }
+
+ ScopeSet scopes;
+
+ if (parsedArgs.ScopeFor) {
+ for (auto const& scope : *parsedArgs.ScopeFor) {
+ if (scope == "VARIABLES"_s) {
+ scopes.insert(ScopeType::VARIABLES);
+ continue;
+ }
+ if (scope == "POLICIES"_s) {
+ scopes.insert(ScopeType::POLICIES);
+ continue;
+ }
+ status.SetError(cmStrCat("SCOPE_FOR unsupported scope \"", scope, '"'));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+ } else {
+ scopes = { ScopeType::VARIABLES, ScopeType::POLICIES };
+ }
+ if (!scopes.contains(ScopeType::VARIABLES) &&
+ !parsedArgs.Propagate.empty()) {
+ status.SetError(
+ "PROPAGATE cannot be specified without a new scope for VARIABLES");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+
+ // create a function blocker
+ auto fb = cm::make_unique<cmBlockFunctionBlocker>(
+ &status.GetMakefile(), scopes, parsedArgs.Propagate);
+ status.GetMakefile().AddFunctionBlocker(std::move(fb));
+
+ return true;
+}
diff --git a/Source/cmBlockCommand.h b/Source/cmBlockCommand.h
new file mode 100644
index 000000000..5fd8f4205
--- /dev/null
+++ b/Source/cmBlockCommand.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+/// Starts block() ... endblock() block
+bool cmBlockCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 0750eeac3..58129a06b 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -474,7 +474,7 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
}
std::string const& key = *args.begin();
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string ValueName;
bool ValueNames = false;
@@ -491,19 +491,15 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
.Bind("SEPARATOR"_s, &Arguments::Separator)
.Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
std::vector<std::string> invalidArgs;
- std::vector<std::string> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args.advance(1), &invalidArgs);
if (!invalidArgs.empty()) {
status.SetError(cmStrCat("given invalid argument(s) \"",
cmJoin(invalidArgs, ", "_s), "\"."));
return false;
}
- if (!keywordsMissingValue.empty()) {
- status.SetError(cmStrCat("missing expected value for argument(s) \"",
- cmJoin(keywordsMissingValue, ", "_s), "\"."));
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if ((!arguments.ValueName.empty() &&
(arguments.ValueNames || arguments.SubKeys)) ||
diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx
index a2aaa2aee..68e658c7d 100644
--- a/Source/cmCMakeLanguageCommand.cxx
+++ b/Source/cmCMakeLanguageCommand.cxx
@@ -14,15 +14,18 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmDependencyProvider.h"
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
namespace {
@@ -33,13 +36,14 @@ bool FatalError(cmExecutionStatus& status, std::string const& error)
return false;
}
-std::array<cm::static_string_view, 12> InvalidCommands{
+std::array<cm::static_string_view, 14> InvalidCommands{
{ // clang-format off
"function"_s, "endfunction"_s,
"macro"_s, "endmacro"_s,
"if"_s, "elseif"_s, "else"_s, "endif"_s,
"while"_s, "endwhile"_s,
- "foreach"_s, "endforeach"_s
+ "foreach"_s, "endforeach"_s,
+ "block"_s, "endblock"_s
} // clang-format on
};
@@ -235,7 +239,7 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
struct SetProviderArgs
{
std::string Command;
- std::vector<std::string> Methods;
+ ArgumentParser::NonEmpty<std::vector<std::string>> Methods;
};
auto const ArgsParser =
@@ -303,6 +307,27 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
return true;
}
+
+bool cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(
+ std::vector<cmListFileArgument> const& args, cmExecutionStatus& status)
+{
+ cmMakefile& makefile = status.GetMakefile();
+ std::vector<std::string> expandedArgs;
+ makefile.ExpandArguments(args, expandedArgs);
+
+ if (args.size() < 2 || expandedArgs.size() > 2) {
+ return FatalError(
+ status,
+ "sub-command GET_MESSAGE_LOG_LEVEL expects exactly one argument");
+ }
+
+ Message::LogLevel logLevel = makefile.GetCurrentLogLevel();
+ std::string outputValue = cmake::LogLevelToString(logLevel);
+
+ const std::string& outputVariable = expandedArgs[1];
+ makefile.AddDefinition(outputVariable, outputValue);
+ return true;
+}
}
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
@@ -451,5 +476,9 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
return cmCMakeLanguageCommandEVAL(args, status);
}
+ if (expArgs[expArg] == "GET_MESSAGE_LOG_LEVEL") {
+ return cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(args, status);
+ }
+
return FatalError(status, "called with unknown meta-operation");
}
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index bf94c2dce..775508223 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakePathCommand.h"
-#include <algorithm>
#include <functional>
#include <iomanip>
#include <map>
@@ -11,10 +10,12 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
@@ -43,15 +44,12 @@ public:
}
template <int Advance = 2>
- Result Parse(std::vector<std::string> const& args,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ Result Parse(std::vector<std::string> const& args) const
{
this->Inputs.clear();
return this->cmArgumentParser<Result>::Parse(
- cmMakeRange(args).advance(Advance), &this->Inputs, keywordsMissingValue,
- parsedKeywords);
+ cmMakeRange(args).advance(Advance), &this->Inputs);
}
const std::vector<std::string>& GetInputs() const { return this->Inputs; }
@@ -82,52 +80,14 @@ public:
template <int Advance = 2>
Result Parse(std::vector<std::string> const& args) const
{
- this->KeywordsMissingValue.clear();
- this->ParsedKeywords.clear();
-
return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
- args, &this->KeywordsMissingValue, &this->ParsedKeywords);
- }
-
- const std::vector<std::string>& GetKeywordsMissingValue() const
- {
- return this->KeywordsMissingValue;
- }
- const std::vector<std::string>& GetParsedKeywords() const
- {
- return this->ParsedKeywords;
- }
-
- bool checkOutputVariable(const Result& arguments,
- cmExecutionStatus& status) const
- {
- if (std::find(this->GetKeywordsMissingValue().begin(),
- this->GetKeywordsMissingValue().end(),
- "OUTPUT_VARIABLE"_s) !=
- this->GetKeywordsMissingValue().end()) {
- status.SetError("OUTPUT_VARIABLE requires an argument.");
- return false;
- }
-
- if (std::find(this->GetParsedKeywords().begin(),
- this->GetParsedKeywords().end(),
- "OUTPUT_VARIABLE"_s) != this->GetParsedKeywords().end() &&
- arguments.Output.empty()) {
- status.SetError("Invalid name for output variable.");
- return false;
- }
-
- return true;
+ args);
}
-
-private:
- mutable std::vector<std::string> KeywordsMissingValue;
- mutable std::vector<std::string> ParsedKeywords;
};
-struct OutputVariable
+struct OutputVariable : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
};
// Usable when OUTPUT_VARIABLE is the only option
class OutputVariableParser
@@ -297,8 +257,8 @@ bool HandleAppendCommand(std::vector<std::string> const& args,
const auto arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1]));
@@ -307,7 +267,7 @@ bool HandleAppendCommand(std::vector<std::string> const& args,
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -319,8 +279,8 @@ bool HandleAppendStringCommand(std::vector<std::string> const& args,
const auto arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
std::string inputPath;
@@ -334,7 +294,7 @@ bool HandleAppendStringCommand(std::vector<std::string> const& args,
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -346,8 +306,8 @@ bool HandleRemoveFilenameCommand(std::vector<std::string> const& args,
const auto arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!parser.GetInputs().empty()) {
@@ -364,7 +324,7 @@ bool HandleRemoveFilenameCommand(std::vector<std::string> const& args,
path.RemoveFileName();
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -376,8 +336,8 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
const auto arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (parser.GetInputs().size() > 1) {
@@ -395,7 +355,7 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
parser.GetInputs().empty() ? "" : parser.GetInputs().front());
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -403,9 +363,9 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args,
bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
bool LastOnly = false;
};
@@ -415,8 +375,8 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
Arguments const arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!parser.GetInputs().empty()) {
@@ -438,7 +398,7 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -446,9 +406,9 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
bool LastOnly = false;
};
@@ -458,8 +418,8 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
Arguments const arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (parser.GetInputs().size() > 1) {
@@ -483,7 +443,7 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -495,8 +455,8 @@ bool HandleNormalPathCommand(std::vector<std::string> const& args,
const auto arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!parser.GetInputs().empty()) {
@@ -512,7 +472,7 @@ bool HandleNormalPathCommand(std::vector<std::string> const& args,
auto path = cmCMakePath(inputPath).Normal();
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -523,10 +483,10 @@ bool HandleTransformPathCommand(
const std::string& base)>& transform,
bool normalizeOption = false)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
- std::string BaseDirectory;
+ cm::optional<ArgumentParser::NonEmpty<std::string>> Output;
+ cm::optional<std::string> BaseDirectory;
bool Normalize = false;
};
@@ -538,8 +498,8 @@ bool HandleTransformPathCommand(
Arguments arguments = parser.Parse(args);
- if (!parser.checkOutputVariable(arguments, status)) {
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!parser.GetInputs().empty()) {
@@ -547,17 +507,11 @@ bool HandleTransformPathCommand(
return false;
}
- if (std::find(parser.GetKeywordsMissingValue().begin(),
- parser.GetKeywordsMissingValue().end(), "BASE_DIRECTORY"_s) !=
- parser.GetKeywordsMissingValue().end()) {
- status.SetError("BASE_DIRECTORY requires an argument.");
- return false;
- }
-
- if (std::find(parser.GetParsedKeywords().begin(),
- parser.GetParsedKeywords().end(),
- "BASE_DIRECTORY"_s) == parser.GetParsedKeywords().end()) {
- arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
+ std::string baseDirectory;
+ if (arguments.BaseDirectory) {
+ baseDirectory = *arguments.BaseDirectory;
+ } else {
+ baseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
std::string inputPath;
@@ -565,13 +519,13 @@ bool HandleTransformPathCommand(
return false;
}
- auto path = transform(cmCMakePath(inputPath), arguments.BaseDirectory);
+ auto path = transform(cmCMakePath(inputPath), baseDirectory);
if (arguments.Normalize) {
path = path.Normal();
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx
index b737c1f29..7325e447d 100644
--- a/Source/cmCMakePresetsGraph.cxx
+++ b/Source/cmCMakePresetsGraph.cxx
@@ -43,6 +43,10 @@ using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
+template <typename T>
+using PresetPair = cmCMakePresetsGraph::PresetPair<T>;
using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
@@ -261,6 +265,8 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset,
if (out->Output) {
CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders,
+ graph.GetVersion(preset));
}
if (out->Filter) {
@@ -301,6 +307,36 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset,
return true;
}
+bool ExpandMacros(const cmCMakePresetsGraph& graph,
+ const PackagePreset& preset,
+ cm::optional<PackagePreset>& out,
+ const std::vector<MacroExpander>& macroExpanders)
+{
+ for (auto& variable : out->Variables) {
+ CHECK_EXPAND(out, variable.second, macroExpanders,
+ graph.GetVersion(preset));
+ }
+
+ CHECK_EXPAND(out, out->ConfigFile, macroExpanders, graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->PackageName, macroExpanders,
+ graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->PackageVersion, macroExpanders,
+ graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->PackageDirectory, macroExpanders,
+ graph.GetVersion(preset));
+ CHECK_EXPAND(out, out->VendorName, macroExpanders, graph.GetVersion(preset));
+
+ return true;
+}
+
+bool ExpandMacros(const cmCMakePresetsGraph& /*graph*/,
+ const WorkflowPreset& /*preset*/,
+ cm::optional<WorkflowPreset>& /*out*/,
+ const std::vector<MacroExpander>& /*macroExpanders*/)
+{
+ return true;
+}
+
template <class T>
bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
cm::optional<T>& out)
@@ -556,6 +592,42 @@ ExpandMacroResult ExpandMacro(std::string& out,
return ExpandMacroResult::Error;
}
+
+template <typename T>
+ReadFileResult SetupWorkflowConfigurePreset(
+ const T& preset, const ConfigurePreset*& configurePreset)
+{
+ if (preset.ConfigurePreset != configurePreset->Name) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ return ReadFileResult::READ_OK;
+}
+
+template <>
+ReadFileResult SetupWorkflowConfigurePreset<ConfigurePreset>(
+ const ConfigurePreset& preset, const ConfigurePreset*& configurePreset)
+{
+ configurePreset = &preset;
+ return ReadFileResult::READ_OK;
+}
+
+template <typename T>
+ReadFileResult TryReachPresetFromWorkflow(
+ const WorkflowPreset& origin,
+ const std::map<std::string, PresetPair<T>>& presets, const std::string& name,
+ const ConfigurePreset*& configurePreset)
+{
+ auto it = presets.find(name);
+ if (it == presets.end()) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ if (!origin.OriginFile->ReachableFiles.count(
+ it->second.Unexpanded.OriginFile)) {
+ return ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE;
+ }
+ return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
+ configurePreset);
+}
}
bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate(
@@ -781,6 +853,7 @@ cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
parentOutput.OutputOnFailure);
InheritOptionalValue(output.Quiet, parentOutput.Quiet);
InheritString(output.OutputLogFile, parentOutput.OutputLogFile);
+ InheritString(output.OutputJUnitFile, parentOutput.OutputJUnitFile);
InheritOptionalValue(output.LabelSummary, parentOutput.LabelSummary);
InheritOptionalValue(output.SubprojectSummary,
parentOutput.SubprojectSummary);
@@ -868,6 +941,57 @@ cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(int /* version */)
return ReadFileResult::READ_OK;
}
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& parentPreset)
+{
+ auto& preset = *this;
+ const PackagePreset& parent =
+ static_cast<const PackagePreset&>(parentPreset);
+
+ InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
+ InheritOptionalValue(preset.InheritConfigureEnvironment,
+ parent.InheritConfigureEnvironment);
+ InheritVector(preset.Generators, parent.Generators);
+ InheritVector(preset.Configurations, parent.Configurations);
+
+ for (auto const& v : parent.Variables) {
+ preset.Variables.insert(v);
+ }
+
+ InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
+ InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput);
+ InheritString(preset.PackageName, parent.PackageName);
+ InheritString(preset.PackageVersion, parent.PackageVersion);
+ InheritString(preset.PackageDirectory, parent.PackageDirectory);
+ InheritString(preset.VendorName, parent.VendorName);
+
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(int /* version */)
+{
+ auto& preset = *this;
+ if (!preset.Hidden && preset.ConfigurePreset.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& /*parentPreset*/)
+{
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(int /* version */)
+{
+ return ReadFileResult::READ_OK;
+}
+
std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir)
{
return cmStrCat(sourceDir, "/CMakePresets.json");
@@ -901,8 +1025,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
std::string filename = GetUserFilename(this->SourceDir);
std::vector<File*> inProgressFiles;
if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(filename, RootType::User,
- ReadReason::Root, inProgressFiles, file);
+ auto result =
+ this->ReadJSONFile(filename, RootType::User, ReadReason::Root,
+ inProgressFiles, file, this->errors);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -910,8 +1035,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
} else {
filename = GetFilename(this->SourceDir);
if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(
- filename, RootType::Project, ReadReason::Root, inProgressFiles, file);
+ auto result =
+ this->ReadJSONFile(filename, RootType::Project, ReadReason::Root,
+ inProgressFiles, file, this->errors);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -928,6 +1054,8 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this));
CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this));
CHECK_OK(ComputePresetInheritance(this->TestPresets, *this));
+ CHECK_OK(ComputePresetInheritance(this->PackagePresets, *this));
+ CHECK_OK(ComputePresetInheritance(this->WorkflowPresets, *this));
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -983,6 +1111,79 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
}
}
+ for (auto& it : this->PackagePresets) {
+ if (!it.second.Unexpanded.Hidden) {
+ const auto configurePreset =
+ this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
+ if (configurePreset == this->ConfigurePresets.end()) {
+ return ReadFileResult::INVALID_CONFIGURE_PRESET;
+ }
+ if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
+ configurePreset->second.Unexpanded.OriginFile)) {
+ return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
+ }
+
+ if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
+ it.second.Unexpanded.Environment.insert(
+ configurePreset->second.Unexpanded.Environment.begin(),
+ configurePreset->second.Unexpanded.Environment.end());
+ }
+ }
+
+ if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ return ReadFileResult::INVALID_MACRO_EXPANSION;
+ }
+ }
+
+ for (auto& it : this->WorkflowPresets) {
+ using Type = WorkflowPreset::WorkflowStep::Type;
+
+ const ConfigurePreset* configurePreset = nullptr;
+ for (auto const& step : it.second.Unexpanded.Steps) {
+ if (configurePreset == nullptr && step.PresetType != Type::Configure) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ if (configurePreset != nullptr && step.PresetType == Type::Configure) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+
+ ReadFileResult result;
+ switch (step.PresetType) {
+ case Type::Configure:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
+ configurePreset);
+ break;
+ case Type::Build:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->BuildPresets, step.PresetName,
+ configurePreset);
+ break;
+ case Type::Test:
+ result =
+ TryReachPresetFromWorkflow(it.second.Unexpanded, this->TestPresets,
+ step.PresetName, configurePreset);
+ break;
+ case Type::Package:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->PackagePresets, step.PresetName,
+ configurePreset);
+ break;
+ }
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ }
+
+ if (configurePreset == nullptr) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+
+ if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ return ReadFileResult::INVALID_MACRO_EXPANSION;
+ }
+ }
+
return ReadFileResult::READ_OK;
}
@@ -1026,6 +1227,10 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED:
return "File version must be 2 or higher for build and test preset "
"support.";
+ case ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED:
+ return "File version must be 6 or higher for package preset support";
+ case ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED:
+ return "File version must be 6 or higher for workflow preset support";
case ReadFileResult::INCLUDE_UNSUPPORTED:
return "File version must be 4 or higher for include support";
case ReadFileResult::INVALID_INCLUDE:
@@ -1047,6 +1252,12 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
case ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED:
return "File version must be 5 or higher for testOutputTruncation "
"preset support.";
+ case ReadFileResult::INVALID_WORKFLOW_STEPS:
+ return "Invalid workflow steps";
+ case ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE:
+ return "Workflow step is unreachable from preset's file";
+ case ReadFileResult::CTEST_JUNIT_UNSUPPORTED:
+ return "File version must be 6 or higher for CTest JUnit output support";
}
return "Unknown error";
@@ -1057,14 +1268,28 @@ void cmCMakePresetsGraph::ClearPresets()
this->ConfigurePresets.clear();
this->BuildPresets.clear();
this->TestPresets.clear();
+ this->PackagePresets.clear();
+ this->WorkflowPresets.clear();
this->ConfigurePresetOrder.clear();
this->BuildPresetOrder.clear();
this->TestPresetOrder.clear();
+ this->PackagePresetOrder.clear();
+ this->WorkflowPresetOrder.clear();
this->Files.clear();
}
+void cmCMakePresetsGraph::printPrecedingNewline(PrintPrecedingNewline* newline)
+{
+ if (newline) {
+ if (*newline == PrintPrecedingNewline::True) {
+ std::cout << std::endl;
+ }
+ *newline = PrintPrecedingNewline::True;
+ }
+}
+
void cmCMakePresetsGraph::PrintPresets(
const std::vector<const cmCMakePresetsGraph::Preset*>& presets)
{
@@ -1093,13 +1318,16 @@ void cmCMakePresetsGraph::PrintPresets(
}
}
-void cmCMakePresetsGraph::PrintConfigurePresetList() const
+void cmCMakePresetsGraph::PrintConfigurePresetList(
+ PrintPrecedingNewline* newline) const
{
- PrintConfigurePresetList([](const ConfigurePreset&) { return true; });
+ PrintConfigurePresetList([](const ConfigurePreset&) { return true; },
+ newline);
}
void cmCMakePresetsGraph::PrintConfigurePresetList(
- const std::function<bool(const ConfigurePreset&)>& filter) const
+ const std::function<bool(const ConfigurePreset&)>& filter,
+ PrintPrecedingNewline* newline) const
{
std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->ConfigurePresetOrder) {
@@ -1112,12 +1340,14 @@ void cmCMakePresetsGraph::PrintConfigurePresetList(
}
if (!presets.empty()) {
+ printPrecedingNewline(newline);
std::cout << "Available configure presets:\n\n";
cmCMakePresetsGraph::PrintPresets(presets);
}
}
-void cmCMakePresetsGraph::PrintBuildPresetList() const
+void cmCMakePresetsGraph::PrintBuildPresetList(
+ PrintPrecedingNewline* newline) const
{
std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->BuildPresetOrder) {
@@ -1130,12 +1360,14 @@ void cmCMakePresetsGraph::PrintBuildPresetList() const
}
if (!presets.empty()) {
+ printPrecedingNewline(newline);
std::cout << "Available build presets:\n\n";
cmCMakePresetsGraph::PrintPresets(presets);
}
}
-void cmCMakePresetsGraph::PrintTestPresetList() const
+void cmCMakePresetsGraph::PrintTestPresetList(
+ PrintPrecedingNewline* newline) const
{
std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->TestPresetOrder) {
@@ -1148,16 +1380,66 @@ void cmCMakePresetsGraph::PrintTestPresetList() const
}
if (!presets.empty()) {
+ printPrecedingNewline(newline);
std::cout << "Available test presets:\n\n";
cmCMakePresetsGraph::PrintPresets(presets);
}
}
+void cmCMakePresetsGraph::PrintPackagePresetList(
+ PrintPrecedingNewline* newline) const
+{
+ this->PrintPackagePresetList([](const PackagePreset&) { return true; },
+ newline);
+}
+
+void cmCMakePresetsGraph::PrintPackagePresetList(
+ const std::function<bool(const PackagePreset&)>& filter,
+ PrintPrecedingNewline* newline) const
+{
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
+ for (auto const& p : this->PackagePresetOrder) {
+ auto const& preset = this->PackagePresets.at(p);
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ printPrecedingNewline(newline);
+ std::cout << "Available package presets:\n\n";
+ cmCMakePresetsGraph::PrintPresets(presets);
+ }
+}
+
+void cmCMakePresetsGraph::PrintWorkflowPresetList(
+ PrintPrecedingNewline* newline) const
+{
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
+ for (auto const& p : this->WorkflowPresetOrder) {
+ auto const& preset = this->WorkflowPresets.at(p);
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ printPrecedingNewline(newline);
+ std::cout << "Available workflow presets:\n\n";
+ cmCMakePresetsGraph::PrintPresets(presets);
+ }
+}
+
void cmCMakePresetsGraph::PrintAllPresets() const
{
- this->PrintConfigurePresetList();
- std::cout << std::endl;
- this->PrintBuildPresetList();
- std::cout << std::endl;
- this->PrintTestPresetList();
+ PrintPrecedingNewline newline = PrintPrecedingNewline::False;
+ this->PrintConfigurePresetList(&newline);
+ this->PrintBuildPresetList(&newline);
+ this->PrintTestPresetList(&newline);
+ this->PrintPackagePresetList(&newline);
+ this->PrintWorkflowPresetList(&newline);
}
diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h
index f1f86629c..17c902ba6 100644
--- a/Source/cmCMakePresetsGraph.h
+++ b/Source/cmCMakePresetsGraph.h
@@ -41,6 +41,8 @@ public:
CONFIGURE_PRESET_UNREACHABLE_FROM_FILE,
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
+ PACKAGE_PRESETS_UNSUPPORTED,
+ WORKFLOW_PRESETS_UNSUPPORTED,
INCLUDE_UNSUPPORTED,
INVALID_INCLUDE,
INVALID_CONFIGURE_PRESET,
@@ -50,8 +52,12 @@ public:
TOOLCHAIN_FILE_UNSUPPORTED,
CYCLIC_INCLUDE,
TEST_OUTPUT_TRUNCATION_UNSUPPORTED,
+ INVALID_WORKFLOW_STEPS,
+ WORKFLOW_STEP_UNREACHABLE_FROM_FILE,
+ CTEST_JUNIT_UNSUPPORTED,
};
+ std::string errors;
enum class ArchToolsetStrategy
{
Set,
@@ -95,7 +101,7 @@ public:
std::string Name;
std::vector<std::string> Inherits;
- bool Hidden;
+ bool Hidden = false;
File* OriginFile;
std::string DisplayName;
std::string Description;
@@ -225,6 +231,7 @@ public:
cm::optional<bool> OutputOnFailure;
cm::optional<bool> Quiet;
std::string OutputLogFile;
+ std::string OutputJUnitFile;
cm::optional<bool> LabelSummary;
cm::optional<bool> SubprojectSummary;
cm::optional<int> MaxPassedTestOutputSize;
@@ -325,6 +332,79 @@ public:
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
+ class PackagePreset : public Preset
+ {
+ public:
+ PackagePreset() = default;
+ PackagePreset(PackagePreset&& /*other*/) = default;
+ PackagePreset(const PackagePreset& /*other*/) = default;
+ PackagePreset& operator=(const PackagePreset& /*other*/) = default;
+ ~PackagePreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ PackagePreset& operator=(PackagePreset&& /*other*/) = default;
+#else
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't.
+ PackagePreset& operator=(PackagePreset&& /*other*/) = delete;
+#endif
+
+ std::string ConfigurePreset;
+ cm::optional<bool> InheritConfigureEnvironment;
+ std::vector<std::string> Generators;
+ std::vector<std::string> Configurations;
+ std::map<std::string, std::string> Variables;
+ std::string ConfigFile;
+
+ cm::optional<bool> DebugOutput;
+ cm::optional<bool> VerboseOutput;
+
+ std::string PackageName;
+ std::string PackageVersion;
+ std::string PackageDirectory;
+ std::string VendorName;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
+ };
+
+ class WorkflowPreset : public Preset
+ {
+ public:
+ WorkflowPreset() = default;
+ WorkflowPreset(WorkflowPreset&& /*other*/) = default;
+ WorkflowPreset(const WorkflowPreset& /*other*/) = default;
+ WorkflowPreset& operator=(const WorkflowPreset& /*other*/) = default;
+ ~WorkflowPreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = default;
+#else
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't.
+ WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = delete;
+#endif
+
+ class WorkflowStep
+ {
+ public:
+ enum class Type
+ {
+ Configure,
+ Build,
+ Test,
+ Package,
+ };
+ Type PresetType;
+ std::string PresetName;
+ };
+
+ std::vector<WorkflowStep> Steps;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
+ };
+
template <class T>
class PresetPair
{
@@ -336,10 +416,14 @@ public:
std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets;
std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
std::map<std::string, PresetPair<TestPreset>> TestPresets;
+ std::map<std::string, PresetPair<PackagePreset>> PackagePresets;
+ std::map<std::string, PresetPair<WorkflowPreset>> WorkflowPresets;
std::vector<std::string> ConfigurePresetOrder;
std::vector<std::string> BuildPresetOrder;
std::vector<std::string> TestPresetOrder;
+ std::vector<std::string> PackagePresetOrder;
+ std::vector<std::string> WorkflowPresetOrder;
std::string SourceDir;
std::vector<std::unique_ptr<File>> Files;
@@ -382,13 +466,27 @@ public:
return "";
}
+ enum class PrintPrecedingNewline
+ {
+ False,
+ True,
+ };
+ static void printPrecedingNewline(PrintPrecedingNewline* p);
+
static void PrintPresets(
const std::vector<const cmCMakePresetsGraph::Preset*>& presets);
- void PrintConfigurePresetList() const;
void PrintConfigurePresetList(
- const std::function<bool(const ConfigurePreset&)>& filter) const;
- void PrintBuildPresetList() const;
- void PrintTestPresetList() const;
+ PrintPrecedingNewline* newline = nullptr) const;
+ void PrintConfigurePresetList(
+ const std::function<bool(const ConfigurePreset&)>& filter,
+ PrintPrecedingNewline* newline = nullptr) const;
+ void PrintBuildPresetList(PrintPrecedingNewline* newline = nullptr) const;
+ void PrintTestPresetList(PrintPrecedingNewline* newline = nullptr) const;
+ void PrintPackagePresetList(PrintPrecedingNewline* newline = nullptr) const;
+ void PrintPackagePresetList(
+ const std::function<bool(const PackagePreset&)>& filter,
+ PrintPrecedingNewline* newline = nullptr) const;
+ void PrintWorkflowPresetList(PrintPrecedingNewline* newline = nullptr) const;
void PrintAllPresets() const;
private:
@@ -407,7 +505,7 @@ private:
ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles);
ReadFileResult ReadJSONFile(const std::string& filename, RootType rootType,
ReadReason readReason,
- std::vector<File*>& inProgressFiles,
- File*& file);
+ std::vector<File*>& inProgressFiles, File*& file,
+ std::string& errMsg);
void ClearPresets();
};
diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h
index f7c73494b..9e47a6988 100644
--- a/Source/cmCMakePresetsGraphInternal.h
+++ b/Source/cmCMakePresetsGraphInternal.h
@@ -147,6 +147,14 @@ cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper(
cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value);
+cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
+ std::vector<cmCMakePresetsGraph::PackagePreset>& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
+ std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
+ const Json::Value* value);
+
cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper(
cmCMakePresetsGraph::ReadFileResult error);
diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx
index d11e839f0..eec53c166 100644
--- a/Source/cmCMakePresetsGraphReadJSON.cxx
+++ b/Source/cmCMakePresetsGraphReadJSON.cxx
@@ -30,11 +30,13 @@ using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 5;
+constexpr int MAX_VERSION = 6;
struct CMakeVersion
{
@@ -46,9 +48,11 @@ struct CMakeVersion
struct RootPresets
{
CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
- std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
- std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
+ std::vector<ConfigurePreset> ConfigurePresets;
+ std::vector<BuildPreset> BuildPresets;
+ std::vector<TestPreset> TestPresets;
+ std::vector<PackagePreset> PackagePresets;
+ std::vector<WorkflowPreset> WorkflowPresets;
std::vector<std::string> Include;
};
@@ -281,6 +285,10 @@ auto const RootPresetsHelper =
cmCMakePresetsGraphInternal::BuildPresetsHelper, false)
.Bind("testPresets"_s, &RootPresets::TestPresets,
cmCMakePresetsGraphInternal::TestPresetsHelper, false)
+ .Bind("packagePresets"_s, &RootPresets::PackagePresets,
+ cmCMakePresetsGraphInternal::PackagePresetsHelper, false)
+ .Bind("workflowPresets"_s, &RootPresets::WorkflowPresets,
+ cmCMakePresetsGraphInternal::WorkflowPresetsHelper, false)
.Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
CMakeVersionHelper, false)
.Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
@@ -411,7 +419,7 @@ cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
const std::string& filename, RootType rootType, ReadReason readReason,
- std::vector<File*>& inProgressFiles, File*& file)
+ std::vector<File*>& inProgressFiles, File*& file, std::string& errMsg)
{
ReadFileResult result;
@@ -430,6 +438,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
cmsys::ifstream fin(filename.c_str());
if (!fin) {
+ errMsg = cmStrCat(filename, ": Failed to read file\n", errMsg);
return ReadFileResult::FILE_NOT_FOUND;
}
// If there's a BOM, toss it.
@@ -438,7 +447,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
Json::Value root;
Json::CharReaderBuilder builder;
Json::CharReaderBuilder::strictMode(&builder.settings_);
- if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ if (!Json::parseFromStream(builder, fin, &root, &errMsg)) {
+ errMsg = cmStrCat(filename, ":\n", errMsg);
return ReadFileResult::JSON_PARSE_ERROR;
}
@@ -456,6 +466,16 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
}
+ // Support for package presets added in version 6.
+ if (v < 6 && root.isMember("packagePresets")) {
+ return ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED;
+ }
+
+ // Support for workflow presets added in version 6.
+ if (v < 6 && root.isMember("workflowPresets")) {
+ return ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED;
+ }
+
// Support for include added in version 4.
if (v < 4 && root.isMember("include")) {
return ReadFileResult::INCLUDE_UNSUPPORTED;
@@ -490,6 +510,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.ConfigurePresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
+ errMsg += R"(\n\t)";
+ errMsg += filename;
return ReadFileResult::INVALID_PRESET;
}
@@ -523,6 +545,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.BuildPresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
+ errMsg += R"(\n\t)";
+ errMsg += filename;
return ReadFileResult::INVALID_PRESET;
}
@@ -564,17 +588,61 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED;
}
+ // Support for outputJUnitFile added in version 6.
+ if (v < 6 && preset.Output && !preset.Output->OutputJUnitFile.empty()) {
+ return ReadFileResult::CTEST_JUNIT_UNSUPPORTED;
+ }
+
this->TestPresetOrder.push_back(preset.Name);
}
+ for (auto& preset : presets.PackagePresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<PackagePreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->PackagePresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3, but this requires version 5
+ // already, so no action needed.
+
+ this->PackagePresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.WorkflowPresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<WorkflowPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->WorkflowPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3, but this requires version 6
+ // already, so no action needed.
+
+ this->WorkflowPresetOrder.push_back(preset.Name);
+ }
+
auto const includeFile = [this, &inProgressFiles, file](
const std::string& include, RootType rootType2,
- ReadReason readReason2) -> ReadFileResult {
+ ReadReason readReason2,
+ std::string& FailureMessage) -> ReadFileResult {
ReadFileResult r;
File* includedFile;
if ((r = this->ReadJSONFile(include, rootType2, readReason2,
- inProgressFiles, includedFile)) !=
- ReadFileResult::READ_OK) {
+ inProgressFiles, includedFile,
+ FailureMessage)) != ReadFileResult::READ_OK) {
return r;
}
@@ -589,8 +657,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
include = cmStrCat(directory, '/', include);
}
- if ((result = includeFile(include, rootType, ReadReason::Included)) !=
- ReadFileResult::READ_OK) {
+ if ((result = includeFile(include, rootType, ReadReason::Included,
+ errMsg)) != ReadFileResult::READ_OK) {
return result;
}
}
@@ -599,7 +667,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
auto cmakePresetsFilename = GetFilename(this->SourceDir);
if (cmSystemTools::FileExists(cmakePresetsFilename)) {
if ((result = includeFile(cmakePresetsFilename, RootType::Project,
- ReadReason::Root)) !=
+ ReadReason::Root, errMsg)) !=
ReadFileResult::READ_OK) {
return result;
}
diff --git a/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx
new file mode 100644
index 000000000..4ae51b1fc
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx
@@ -0,0 +1,95 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+
+auto const OutputHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("debug"_s, &PackagePreset::DebugOutput,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("verbose"_s, &PackagePreset::VerboseOutput,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+
+auto const VariableHelper = cmJSONHelperBuilder<ReadFileResult>::String(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+auto const VariablesHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Map<std::string>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PackagePresetHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &PackagePreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind("inherits"_s, &PackagePreset::Inherits,
+ cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+ false)
+ .Bind("hidden"_s, &PackagePreset::Hidden,
+ cmCMakePresetsGraphInternal::PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &PackagePreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &PackagePreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("environment"_s, &PackagePreset::Environment,
+ cmCMakePresetsGraphInternal::EnvironmentMapHelper, false)
+ .Bind("configurePreset"_s, &PackagePreset::ConfigurePreset,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &PackagePreset::InheritConfigureEnvironment,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("generators"_s, &PackagePreset::Generators,
+ cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+ .Bind("configurations"_s, &PackagePreset::Configurations,
+ cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+ .Bind("variables"_s, &PackagePreset::Variables, VariablesHelper, false)
+ .Bind("configFile"_s, &PackagePreset::ConfigFile,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("output"_s, OutputHelper, false)
+ .Bind("packageName"_s, &PackagePreset::PackageName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("packageVersion"_s, &PackagePreset::PackageVersion,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("packageDirectory"_s, &PackagePreset::PackageDirectory,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("vendorName"_s, &PackagePreset::VendorName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("condition"_s, &PackagePreset::ConditionEvaluator,
+ cmCMakePresetsGraphInternal::PresetConditionHelper, false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
+ std::vector<cmCMakePresetsGraph::PackagePreset>& out,
+ const Json::Value* value)
+{
+ static auto const helper =
+ cmJSONHelperBuilder<ReadFileResult>::Vector<PackagePreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ PackagePresetHelper);
+
+ return helper(out, value);
+}
+}
diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
index c07d38026..3856f630c 100644
--- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
+++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
@@ -104,6 +104,8 @@ auto const TestPresetOptionalOutputHelper =
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("outputJUnitFile"_s, &TestPreset::OutputOptions::OutputJUnitFile,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
.Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("subprojectSummary"_s,
diff --git a/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
new file mode 100644
index 000000000..33680a182
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
@@ -0,0 +1,95 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
+
+ReadFileResult WorkflowStepTypeHelper(WorkflowPreset::WorkflowStep::Type& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "configure") {
+ out = WorkflowPreset::WorkflowStep::Type::Configure;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "build") {
+ out = WorkflowPreset::WorkflowStep::Type::Build;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "test") {
+ out = WorkflowPreset::WorkflowStep::Type::Test;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "package") {
+ out = WorkflowPreset::WorkflowStep::Type::Package;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const WorkflowStepHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset::WorkflowStep>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("type"_s, &WorkflowPreset::WorkflowStep::PresetType,
+ WorkflowStepTypeHelper)
+ .Bind("name"_s, &WorkflowPreset::WorkflowStep::PresetName,
+ cmCMakePresetsGraphInternal::PresetStringHelper);
+
+auto const WorkflowStepsHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset::WorkflowStep>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ WorkflowStepHelper);
+
+auto const WorkflowPresetHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &WorkflowPreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &WorkflowPreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &WorkflowPreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("steps"_s, &WorkflowPreset::Steps, WorkflowStepsHelper);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
+ std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
+ const Json::Value* value)
+{
+ static auto const helper =
+ cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ WorkflowPresetHelper);
+
+ return helper(out, value);
+}
+}
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 66507a73e..f60a1e999 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -2116,11 +2116,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
return false;
}
i++;
- this->Impl->TestHandler.SetJUnitXMLFileName(std::string(args[i]));
- // Turn test output compression off.
- // This makes it easier to include test output in the resulting
- // JUnit XML report.
- this->Impl->CompressTestOutput = false;
+ this->SetOutputJUnitFileName(std::string(args[i]));
}
cm::string_view noTestsPrefix = "--no-tests=";
@@ -2458,6 +2454,9 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (!expandedPreset->Output->OutputLogFile.empty()) {
this->SetOutputLogFileName(expandedPreset->Output->OutputLogFile);
}
+ if (!expandedPreset->Output->OutputJUnitFile.empty()) {
+ this->SetOutputJUnitFileName(expandedPreset->Output->OutputJUnitFile);
+ }
this->Impl->LabelSummary =
expandedPreset->Output->LabelSummary.value_or(true);
@@ -3541,6 +3540,15 @@ void cmCTest::SetOutputLogFileName(const std::string& name)
}
}
+void cmCTest::SetOutputJUnitFileName(const std::string& name)
+{
+ this->Impl->TestHandler.SetJUnitXMLFileName(name);
+ // Turn test output compression off.
+ // This makes it easier to include test output in the resulting
+ // JUnit XML report.
+ this->Impl->CompressTestOutput = false;
+}
+
static const char* cmCTestStringLogType[] = { "DEBUG",
"OUTPUT",
"HANDLER_OUTPUT",
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 551c116ad..0017b3e19 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -359,6 +359,9 @@ public:
/** Set the output log file name */
void SetOutputLogFileName(const std::string& name);
+ /** Set the output JUnit file name */
+ void SetOutputJUnitFileName(const std::string& name);
+
/** Set the visual studio or Xcode config type */
void SetConfigType(const std::string& ct);
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index c6296f9f4..27f21567a 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -14,13 +14,13 @@
#include "cmAddLibraryCommand.h"
#include "cmAddSubDirectoryCommand.h"
#include "cmAddTestCommand.h"
+#include "cmBlockCommand.h"
#include "cmBreakCommand.h"
#include "cmBuildCommand.h"
#include "cmCMakeLanguageCommand.h"
#include "cmCMakeMinimumRequired.h"
#include "cmCMakePathCommand.h"
#include "cmCMakePolicyCommand.h"
-#include "cmCommand.h"
#include "cmConfigureFileCommand.h"
#include "cmContinueCommand.h"
#include "cmCreateTestSourceList.h"
@@ -127,6 +127,7 @@ void GetScriptingCommands(cmState* state)
state->AddFlowControlCommand("macro", cmMacroCommand);
state->AddFlowControlCommand("return", cmReturnCommand);
state->AddFlowControlCommand("while", cmWhileCommand);
+ state->AddFlowControlCommand("block", cmBlockCommand);
state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand);
state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired);
@@ -199,6 +200,10 @@ void GetScriptingCommands(cmState* state)
"An ENDWHILE command was found outside of a proper "
"WHILE ENDWHILE structure. Or its arguments did not "
"match the opening WHILE command.");
+ state->AddUnexpectedFlowControlCommand(
+ "endblock",
+ "An ENDBLOCK command was found outside of a proper "
+ "BLOCK ENDBLOCK structure.");
#if !defined(CMAKE_BOOTSTRAP)
state->AddBuiltinCommand("cmake_host_system_information",
@@ -220,6 +225,8 @@ void GetScriptingCommands(cmState* state)
void GetProjectCommands(cmState* state)
{
+ state->AddBuiltinCommand("add_compile_definitions",
+ cmAddCompileDefinitionsCommand);
state->AddBuiltinCommand("add_custom_command", cmAddCustomCommandCommand);
state->AddBuiltinCommand("add_custom_target", cmAddCustomTargetCommand);
state->AddBuiltinCommand("add_definitions", cmAddDefinitionsCommand);
@@ -264,15 +271,12 @@ void GetProjectCommands(cmState* state)
cmTargetLinkLibrariesCommand);
state->AddBuiltinCommand("target_link_options", cmTargetLinkOptionsCommand);
state->AddBuiltinCommand("target_sources", cmTargetSourcesCommand);
- state->AddBuiltinCommand("try_compile",
- cm::make_unique<cmTryCompileCommand>());
- state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>());
+ state->AddBuiltinCommand("try_compile", cmTryCompileCommand);
+ state->AddBuiltinCommand("try_run", cmTryRunCommand);
state->AddBuiltinCommand("target_precompile_headers",
cmTargetPrecompileHeadersCommand);
#if !defined(CMAKE_BOOTSTRAP)
- state->AddBuiltinCommand("add_compile_definitions",
- cmAddCompileDefinitionsCommand);
state->AddBuiltinCommand("add_compile_options", cmAddCompileOptionsCommand);
state->AddBuiltinCommand("aux_source_directory",
cmAuxSourceDirectoryCommand);
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index ba95168d6..5fe6756b1 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
@@ -175,6 +176,9 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
cmLocalGenerator* lg = linkee->GetLocalGenerator();
std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
lg->GetTargetDirectory(linkee));
+ if (lg->GetGlobalGenerator()->IsMultiConfig()) {
+ di = cmStrCat(di, '/', config);
+ }
dirs.push_back(std::move(di));
}
}
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index cda70fc1a..044f69f00 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1566,8 +1566,9 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
if (target->IsFrameworkOnApple() && !this->GlobalGenerator->IsXcode()) {
// Add the framework directory and the framework item itself
- auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item.Value, true);
- if (!fwItems) {
+ auto fwDescriptor = this->GlobalGenerator->SplitFrameworkPath(
+ item.Value, cmGlobalGenerator::FrameworkFormat::Extended);
+ if (!fwDescriptor) {
this->CMakeInstance->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Could not parse framework path \"", item.Value,
@@ -1575,12 +1576,13 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
item.Backtrace);
return;
}
- if (!fwItems->first.empty()) {
+ if (!fwDescriptor->Directory.empty()) {
// Add the directory portion to the framework search path.
- this->AddFrameworkPath(fwItems->first);
+ this->AddFrameworkPath(fwDescriptor->Directory);
}
if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s)) {
- this->Items.emplace_back(fwItems->second, ItemIsPath::Yes, target,
+ this->Items.emplace_back(fwDescriptor->GetLinkName(), ItemIsPath::Yes,
+ target,
this->FindLibraryFeature(entry.Feature));
} else {
this->Items.emplace_back(
@@ -1851,9 +1853,11 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
std::string const& item = entry.Item.Value;
// Try to separate the framework name and path.
- auto fwItems =
- this->GlobalGenerator->SplitFrameworkPath(item, entry.Feature != DEFAULT);
- if (!fwItems) {
+ auto fwDescriptor = this->GlobalGenerator->SplitFrameworkPath(
+ item,
+ entry.Feature == DEFAULT ? cmGlobalGenerator::FrameworkFormat::Relaxed
+ : cmGlobalGenerator::FrameworkFormat::Extended);
+ if (!fwDescriptor) {
std::ostringstream e;
e << "Could not parse framework path \"" << item << "\" "
<< "linked by target " << this->Target->GetName() << ".";
@@ -1861,18 +1865,14 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
return;
}
- std::string fw_path = std::move(fwItems->first);
- std::string fw = std::move(fwItems->second);
- std::string full_fw = cmStrCat(fw, ".framework/", fw);
-
+ const std::string& fw_path = fwDescriptor->Directory;
if (!fw_path.empty()) {
- full_fw = cmStrCat(fw_path, '/', full_fw);
// Add the directory portion to the framework search path.
this->AddFrameworkPath(fw_path);
}
// add runtime information
- this->AddLibraryRuntimeInfo(full_fw);
+ this->AddLibraryRuntimeInfo(fwDescriptor->GetFullPath());
if (entry.Feature == DEFAULT) {
// ensure FRAMEWORK feature is loaded
@@ -1887,9 +1887,9 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
? "FRAMEWORK"
: entry.Feature));
} else {
- this->Items.emplace_back(fw, ItemIsPath::Yes, nullptr,
- this->FindLibraryFeature(entry.Feature == DEFAULT
- ? "FRAMEWORK"
+ this->Items.emplace_back(
+ fwDescriptor->GetLinkName(), ItemIsPath::Yes, nullptr,
+ this->FindLibraryFeature(entry.Feature == DEFAULT ? "FRAMEWORK"
: entry.Feature));
}
}
@@ -2252,15 +2252,11 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
// It could be an Apple framework
if (!is_shared_library) {
- if (fullPath.find(".framework") != std::string::npos) {
- static cmsys::RegularExpression splitFramework(
- "^(.*)/(.*).framework/(.*)$");
- if (splitFramework.find(fullPath) &&
- (std::string::npos !=
- splitFramework.match(3).find(splitFramework.match(2)))) {
- is_shared_library = true;
- }
- }
+ is_shared_library =
+ this->GlobalGenerator
+ ->SplitFrameworkPath(fullPath,
+ cmGlobalGenerator::FrameworkFormat::Strict)
+ .has_value();
}
if (!is_shared_library) {
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 6a419f681..90f3de0a1 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -14,10 +14,15 @@
#pragma warning(disable : 1572) /* floating-point equality test */
#endif
+#if defined(__LCC__) && defined(__EDG__) && (__LCC__ == 123)
+#pragma diag_suppress 2910 /* excess -Wunused-function in 1.23.x */
+#endif
+
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
#cmakedefine CMake_USE_MACH_PARSER
#cmakedefine CMake_USE_XCOFF_PARSER
+#cmakedefine CMAKE_USE_WMAKE
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
@@ -28,3 +33,11 @@
#if defined(_WIN32) && !defined(NOMINMAX)
# define NOMINMAX
#endif
+
+#cmakedefine CURL_CA_BUNDLE "@CURL_CA_BUNDLE@"
+#cmakedefine CURL_CA_PATH "@CURL_CA_PATH@"
+
+#cmakedefine01 CMake_STAT_HAS_ST_MTIM
+#cmakedefine01 CMake_STAT_HAS_ST_MTIMESPEC
+
+#cmakedefine KWSYS_ENCODING_DEFAULT_CODEPAGE @KWSYS_ENCODING_DEFAULT_CODEPAGE@
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index b1d37a6ff..867f984fd 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCoreTryCompile.h"
+#include <array>
#include <cstdio>
#include <cstring>
#include <set>
@@ -12,13 +13,16 @@
#include <cmext/string_view>
#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmArgumentParser.h"
#include "cmExportTryCompileFileGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -28,142 +32,7 @@
#include "cmake.h"
namespace {
-class LanguageStandardState
-{
-public:
- LanguageStandardState(std::string&& lang)
- : StandardFlag(lang + "_STANDARD")
- , RequiredFlag(lang + "_STANDARD_REQUIRED")
- , ExtensionFlag(lang + "_EXTENSIONS")
- {
- }
-
- void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; }
-
- bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index)
- {
- bool updated = false;
- if (argv[index] == this->StandardFlag) {
- this->DidStandard = true;
- this->StandardValue = argv[++index];
- updated = true;
- } else if (argv[index] == this->RequiredFlag) {
- this->DidStandardRequired = true;
- this->RequiredValue = argv[++index];
- updated = true;
- } else if (argv[index] == this->ExtensionFlag) {
- this->DidExtensions = true;
- this->ExtensionValue = argv[++index];
- updated = true;
- }
- return updated;
- }
-
- bool Validate(cmMakefile* const makefile) const
- {
- if (this->DidStandard) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->StandardFlag,
- " allowed only in source file signature."));
- return false;
- }
- if (this->DidStandardRequired) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->RequiredFlag,
- " allowed only in source file signature."));
- return false;
- }
- if (this->DidExtensions) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->ExtensionFlag,
- " allowed only in source file signature."));
- return false;
- }
-
- return true;
- }
-
- bool DidNone() const
- {
- return !this->DidStandard && !this->DidStandardRequired &&
- !this->DidExtensions;
- }
-
- void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard,
- bool warnCMP0067,
- std::vector<std::string>& warnCMP0067Variables)
- {
- if (!this->IsEnabled) {
- return;
- }
-
- auto lookupStdVar = [&](std::string const& var) -> std::string {
- std::string value = makefile->GetSafeDefinition(var);
- if (warnCMP0067 && !value.empty()) {
- value.clear();
- warnCMP0067Variables.emplace_back(var);
- }
- return value;
- };
-
- if (honorStandard || warnCMP0067) {
- if (!this->DidStandard) {
- this->StandardValue =
- lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag));
- }
- if (!this->DidStandardRequired) {
- this->RequiredValue =
- lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag));
- }
- if (!this->DidExtensions) {
- this->ExtensionValue =
- lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag));
- }
- }
- }
-
- void WriteProperties(FILE* fout, std::string const& targetName) const
- {
- if (!this->IsEnabled) {
- return;
- }
-
- auto writeProp = [&](std::string const& prop, std::string const& value) {
- fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
- targetName.c_str(),
- cmOutputConverter::EscapeForCMake(prop).c_str(),
- cmOutputConverter::EscapeForCMake(value).c_str());
- };
-
- if (!this->StandardValue.empty()) {
- writeProp(this->StandardFlag, this->StandardValue);
- }
- if (!this->RequiredValue.empty()) {
- writeProp(this->RequiredFlag, this->RequiredValue);
- }
- if (!this->ExtensionValue.empty()) {
- writeProp(this->ExtensionFlag, this->ExtensionValue);
- }
- }
-
-private:
- bool IsEnabled = false;
- bool DidStandard = false;
- bool DidStandardRequired = false;
- bool DidExtensions = false;
-
- std::string StandardFlag;
- std::string RequiredFlag;
- std::string ExtensionFlag;
-
- std::string StandardValue;
- std::string RequiredValue;
- std::string ExtensionValue;
-};
-
+constexpr const char* unique_binary_directory = "CMAKE_BINARY_DIR_USE_MKDTEMP";
constexpr size_t lang_property_start = 0;
constexpr size_t lang_property_size = 4;
constexpr size_t pie_property_start = 4;
@@ -226,6 +95,8 @@ std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT =
"CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT";
+std::string const kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT =
+ "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT";
/* GHS Multi platform variables */
std::set<std::string> const ghs_platform_vars{
@@ -233,114 +104,249 @@ std::set<std::string> const ghs_platform_vars{
"GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME",
"GHS_OS_DIR_OPTION"
};
+using Arguments = cmCoreTryCompile::Arguments;
+
+ArgumentParser::Continue TryCompileLangProp(Arguments& args,
+ cm::string_view key,
+ cm::string_view val)
+{
+ args.LangProps[std::string(key)] = std::string(val);
+ return ArgumentParser::Continue::No;
+}
+
+ArgumentParser::Continue TryCompileCompileDefs(Arguments& args,
+ cm::string_view val)
+{
+ cmExpandList(val, args.CompileDefs);
+ return ArgumentParser::Continue::Yes;
}
-int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
- bool isTryRun)
+cmArgumentParser<Arguments> makeTryCompileParser(
+ const cmArgumentParser<Arguments>& base)
+{
+ return cmArgumentParser<Arguments>{ base }.Bind("OUTPUT_VARIABLE"_s,
+ &Arguments::OutputVariable);
+}
+
+cmArgumentParser<Arguments> makeTryRunParser(
+ const cmArgumentParser<Arguments>& base)
+{
+ return cmArgumentParser<Arguments>{ base }
+ .Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
+ .Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
+ .Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
+ .Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable)
+ .Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory)
+ .Bind("ARGS"_s, &Arguments::RunArgs)
+ /* keep semicolon on own line */;
+}
+
+#define BIND_LANG_PROPS(lang) \
+ Bind(#lang "_STANDARD"_s, TryCompileLangProp) \
+ .Bind(#lang "_STANDARD_REQUIRED"_s, TryCompileLangProp) \
+ .Bind(#lang "_EXTENSIONS"_s, TryCompileLangProp)
+
+auto const TryCompileBaseArgParser =
+ cmArgumentParser<Arguments>{}
+ .Bind(0, &Arguments::CompileResultVariable)
+ .Bind("NO_CACHE"_s, &Arguments::NoCache)
+ .Bind("CMAKE_FLAGS"_s, &Arguments::CMakeFlags)
+ .Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal)
+ /* keep semicolon on own line */;
+
+auto const TryCompileBaseSourcesArgParser =
+ cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
+ .Bind("SOURCES"_s, &Arguments::Sources)
+ .Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs,
+ ArgumentParser::ExpectAtLeast{ 0 })
+ .Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries)
+ .Bind("LINK_OPTIONS"_s, &Arguments::LinkOptions)
+ .Bind("COPY_FILE"_s, &Arguments::CopyFileTo)
+ .Bind("COPY_FILE_ERROR"_s, &Arguments::CopyFileError)
+ .BIND_LANG_PROPS(C)
+ .BIND_LANG_PROPS(CUDA)
+ .BIND_LANG_PROPS(CXX)
+ .BIND_LANG_PROPS(HIP)
+ .BIND_LANG_PROPS(OBJC)
+ .BIND_LANG_PROPS(OBJCXX)
+ /* keep semicolon on own line */;
+
+auto const TryCompileBaseNewSourcesArgParser =
+ cmArgumentParser<Arguments>{ TryCompileBaseSourcesArgParser }
+ .Bind("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent)
+ .Bind("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar)
+ .Bind("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile)
+ /* keep semicolon on own line */;
+
+auto const TryCompileBaseProjectArgParser =
+ cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
+ .Bind("PROJECT"_s, &Arguments::ProjectName)
+ .Bind("SOURCE_DIR"_s, &Arguments::SourceDirectoryOrFile)
+ .Bind("BINARY_DIR"_s, &Arguments::BinaryDirectory)
+ .Bind("TARGET"_s, &Arguments::TargetName)
+ /* keep semicolon on own line */;
+
+auto const TryCompileProjectArgParser =
+ makeTryCompileParser(TryCompileBaseProjectArgParser);
+
+auto const TryCompileSourcesArgParser =
+ makeTryCompileParser(TryCompileBaseNewSourcesArgParser);
+
+auto const TryCompileOldArgParser =
+ makeTryCompileParser(TryCompileBaseSourcesArgParser)
+ .Bind(1, &Arguments::BinaryDirectory)
+ .Bind(2, &Arguments::SourceDirectoryOrFile)
+ .Bind(3, &Arguments::ProjectName)
+ .Bind(4, &Arguments::TargetName)
+ /* keep semicolon on own line */;
+
+auto const TryRunSourcesArgParser =
+ makeTryRunParser(TryCompileBaseNewSourcesArgParser);
+
+auto const TryRunOldArgParser = makeTryRunParser(TryCompileOldArgParser);
+
+#undef BIND_LANG_PROPS
+}
+
+Arguments cmCoreTryCompile::ParseArgs(
+ const cmRange<std::vector<std::string>::const_iterator>& args,
+ const cmArgumentParser<Arguments>& parser,
+ std::vector<std::string>& unparsedArguments)
+{
+ auto arguments = parser.Parse(args, &unparsedArguments, 0);
+ if (!arguments.MaybeReportError(*(this->Makefile)) &&
+ !unparsedArguments.empty()) {
+ std::string m = "Unknown arguments:";
+ for (const auto& i : unparsedArguments) {
+ m = cmStrCat(m, "\n \"", i, "\"");
+ }
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m);
+ }
+ return arguments;
+}
+
+Arguments cmCoreTryCompile::ParseArgs(
+ cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun)
+{
+ std::vector<std::string> unparsedArguments;
+ const auto& second = *(++args.begin());
+
+ if (!isTryRun && second == "PROJECT") {
+ // New PROJECT signature (try_compile only).
+ auto arguments =
+ this->ParseArgs(args, TryCompileProjectArgParser, unparsedArguments);
+ if (!arguments.BinaryDirectory) {
+ arguments.BinaryDirectory = unique_binary_directory;
+ }
+ return arguments;
+ }
+
+ if (cmHasLiteralPrefix(second, "SOURCE")) {
+ // New SOURCES signature.
+ auto arguments = this->ParseArgs(
+ args, isTryRun ? TryRunSourcesArgParser : TryCompileSourcesArgParser,
+ unparsedArguments);
+ arguments.BinaryDirectory = unique_binary_directory;
+ return arguments;
+ }
+
+ // Old signature.
+ auto arguments = this->ParseArgs(
+ args, isTryRun ? TryRunOldArgParser : TryCompileOldArgParser,
+ unparsedArguments);
+ // For historical reasons, treat some empty-valued keyword
+ // arguments as if they were not specified at all.
+ if (arguments.OutputVariable && arguments.OutputVariable->empty()) {
+ arguments.OutputVariable = cm::nullopt;
+ }
+ if (isTryRun) {
+ if (arguments.CompileOutputVariable &&
+ arguments.CompileOutputVariable->empty()) {
+ arguments.CompileOutputVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputVariable && arguments.RunOutputVariable->empty()) {
+ arguments.RunOutputVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputStdOutVariable &&
+ arguments.RunOutputStdOutVariable->empty()) {
+ arguments.RunOutputStdOutVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputStdErrVariable &&
+ arguments.RunOutputStdErrVariable->empty()) {
+ arguments.RunOutputStdErrVariable = cm::nullopt;
+ }
+ if (arguments.RunWorkingDirectory &&
+ arguments.RunWorkingDirectory->empty()) {
+ arguments.RunWorkingDirectory = cm::nullopt;
+ }
+ }
+ return arguments;
+}
+
+bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
+ cmStateEnums::TargetType targetType)
{
- this->BinaryDirectory = argv[1];
this->OutputFile.clear();
// which signature were we called with ?
this->SrcFileSignature = true;
- cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
- cmValue tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
- if (!isTryRun && cmNonempty(tt)) {
- if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) {
- targetType = cmStateEnums::EXECUTABLE;
- } else if (*tt ==
- cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) {
- targetType = cmStateEnums::STATIC_LIBRARY;
- } else {
+ bool useUniqueBinaryDirectory = false;
+ std::string sourceDirectory;
+ std::string projectName;
+ std::string targetName;
+ if (arguments.ProjectName) {
+ this->SrcFileSignature = false;
+ if (!arguments.SourceDirectoryOrFile ||
+ arguments.SourceDirectoryOrFile->empty()) {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "No <srcdir> specified.");
+ return false;
+ }
+ sourceDirectory = *arguments.SourceDirectoryOrFile;
+ projectName = *arguments.ProjectName;
+ if (arguments.TargetName) {
+ targetName = *arguments.TargetName;
+ }
+ } else {
+ projectName = "CMAKE_TRY_COMPILE";
+ /* Use a random file name to avoid rapid creation and deletion
+ of the same executable name (some filesystems fail on that). */
+ char targetNameBuf[64];
+ snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
+ cmSystemTools::RandomSeed() & 0xFFFFF);
+ targetName = targetNameBuf;
+ }
+
+ if (!arguments.BinaryDirectory || arguments.BinaryDirectory->empty()) {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "No <bindir> specified.");
+ return false;
+ }
+ if (*arguments.BinaryDirectory == unique_binary_directory) {
+ // leave empty until we're ready to create it, so we don't try to remove
+ // a non-existing directory if we abort due to e.g. bad arguments
+ this->BinaryDirectory.clear();
+ useUniqueBinaryDirectory = true;
+ } else {
+ if (!cmSystemTools::FileIsFullPath(*arguments.BinaryDirectory)) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("Invalid value '", *tt,
- "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '",
- cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE),
- "' and '",
- cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY),
- "' are allowed."));
- return -1;
+ cmStrCat("<bindir> is not an absolute path:\n '",
+ *arguments.BinaryDirectory, "'"));
+ return false;
+ }
+ this->BinaryDirectory = *arguments.BinaryDirectory;
+ // compute the binary dir when TRY_COMPILE is called with a src file
+ // signature
+ if (this->SrcFileSignature) {
+ this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
}
}
- std::string sourceDirectory = argv[2];
- std::string projectName;
- std::string targetName;
- std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0]
- std::vector<std::string> compileDefs;
- std::string cmakeInternal;
- std::string outputVariable;
- std::string copyFile;
- std::string copyFileError;
- LanguageStandardState cState("C");
- LanguageStandardState cudaState("CUDA");
- LanguageStandardState cxxState("CXX");
- LanguageStandardState hipState("HIP");
- LanguageStandardState objcState("OBJC");
- LanguageStandardState objcxxState("OBJCXX");
std::vector<std::string> targets;
- std::vector<std::string> linkOptions;
- std::string libsToLink = " ";
- bool useOldLinkLibs = true;
- char targetNameBuf[64];
- bool didOutputVariable = false;
- bool didCopyFile = false;
- bool didCopyFileError = false;
- bool useSources = argv[2] == "SOURCES";
- std::vector<std::string> sources;
-
- enum Doing
- {
- DoingNone,
- DoingCMakeFlags,
- DoingCompileDefinitions,
- DoingLinkOptions,
- DoingLinkLibraries,
- DoingOutputVariable,
- DoingCopyFile,
- DoingCopyFileError,
- DoingSources,
- DoingCMakeInternal
- };
- Doing doing = useSources ? DoingSources : DoingNone;
- for (size_t i = 3; i < argv.size(); ++i) {
- if (argv[i] == "CMAKE_FLAGS") {
- doing = DoingCMakeFlags;
- } else if (argv[i] == "COMPILE_DEFINITIONS") {
- doing = DoingCompileDefinitions;
- } else if (argv[i] == "LINK_OPTIONS") {
- doing = DoingLinkOptions;
- } else if (argv[i] == "LINK_LIBRARIES") {
- doing = DoingLinkLibraries;
- useOldLinkLibs = false;
- } else if (argv[i] == "OUTPUT_VARIABLE") {
- doing = DoingOutputVariable;
- didOutputVariable = true;
- } else if (argv[i] == "COPY_FILE") {
- doing = DoingCopyFile;
- didCopyFile = true;
- } else if (argv[i] == "COPY_FILE_ERROR") {
- doing = DoingCopyFileError;
- didCopyFileError = true;
- } else if (cState.UpdateIfMatches(argv, i) ||
- cxxState.UpdateIfMatches(argv, i) ||
- cudaState.UpdateIfMatches(argv, i) ||
- hipState.UpdateIfMatches(argv, i) ||
- objcState.UpdateIfMatches(argv, i) ||
- objcxxState.UpdateIfMatches(argv, i)) {
- continue;
- } else if (argv[i] == "__CMAKE_INTERNAL") {
- doing = DoingCMakeInternal;
- } else if (doing == DoingCMakeFlags) {
- cmakeFlags.emplace_back(argv[i]);
- } else if (doing == DoingCompileDefinitions) {
- cmExpandList(argv[i], compileDefs);
- } else if (doing == DoingLinkOptions) {
- linkOptions.emplace_back(argv[i]);
- } else if (doing == DoingLinkLibraries) {
- libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" ";
- if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
+ if (arguments.LinkLibraries) {
+ for (std::string const& i : *arguments.LinkLibraries) {
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(i)) {
switch (tgt->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
@@ -359,114 +365,94 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"IMPORTED LINK_LIBRARIES. Got ",
tgt->GetName(), " of type ",
cmState::GetTargetTypeName(tgt->GetType()), "."));
- return -1;
+ return false;
}
if (tgt->IsImported()) {
- targets.emplace_back(argv[i]);
+ targets.emplace_back(i);
}
}
- } else if (doing == DoingOutputVariable) {
- outputVariable = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCopyFile) {
- copyFile = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCopyFileError) {
- copyFileError = argv[i];
- doing = DoingNone;
- } else if (doing == DoingSources) {
- sources.emplace_back(argv[i]);
- } else if (doing == DoingCMakeInternal) {
- cmakeInternal = argv[i];
- doing = DoingNone;
- } else if (i == 3) {
- this->SrcFileSignature = false;
- projectName = argv[i];
- } else if (i == 4 && !this->SrcFileSignature) {
- targetName = argv[i];
- } else {
- std::ostringstream m;
- m << "try_compile given unknown argument \"" << argv[i] << "\".";
- this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str());
}
}
- if (didCopyFile && copyFile.empty()) {
+ if (arguments.CopyFileTo && arguments.CopyFileTo->empty()) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"COPY_FILE must be followed by a file path");
- return -1;
+ return false;
}
- if (didCopyFileError && copyFileError.empty()) {
+ if (arguments.CopyFileError && arguments.CopyFileError->empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COPY_FILE_ERROR must be followed by a variable name");
- return -1;
+ return false;
}
- if (didCopyFileError && !didCopyFile) {
+ if (arguments.CopyFileError && !arguments.CopyFileTo) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COPY_FILE_ERROR may be used only with COPY_FILE");
- return -1;
- }
-
- if (didOutputVariable && outputVariable.empty()) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "OUTPUT_VARIABLE must be followed by a variable name");
- return -1;
+ return false;
}
- if (useSources && sources.empty()) {
+ if (arguments.Sources && arguments.Sources->empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"SOURCES must be followed by at least one source file");
- return -1;
+ return false;
}
- if (!this->SrcFileSignature) {
- if (!cState.Validate(this->Makefile)) {
- return -1;
- }
- if (!cudaState.Validate(this->Makefile)) {
- return -1;
- }
- if (!hipState.Validate(this->Makefile)) {
- return -1;
- }
- if (!cxxState.Validate(this->Makefile)) {
- return -1;
+ if (this->SrcFileSignature) {
+ if (arguments.SourceFromContent &&
+ arguments.SourceFromContent->size() % 2) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "SOURCE_FROM_CONTENT requires exactly two arguments");
+ return false;
}
- if (!objcState.Validate(this->Makefile)) {
- return -1;
+ if (arguments.SourceFromVar && arguments.SourceFromVar->size() % 2) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "SOURCE_FROM_VAR requires exactly two arguments");
+ return false;
}
- if (!objcxxState.Validate(this->Makefile)) {
- return -1;
+ if (arguments.SourceFromFile && arguments.SourceFromFile->size() % 2) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "SOURCE_FROM_FILE requires exactly two arguments");
+ return false;
}
- }
-
- // compute the binary dir when TRY_COMPILE is called with a src file
- // signature
- if (this->SrcFileSignature) {
- this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
} else {
// only valid for srcfile signatures
- if (!compileDefs.empty()) {
+ if (!arguments.LangProps.empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(arguments.LangProps.begin()->first,
+ " allowed only in source file signature"));
+ return false;
+ }
+ if (!arguments.CompileDefs.empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE");
- return -1;
+ "COMPILE_DEFINITIONS allowed only in source file signature");
+ return false;
}
- if (!copyFile.empty()) {
+ if (arguments.CopyFileTo) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- "COPY_FILE specified on a srcdir type TRY_COMPILE");
- return -1;
+ "COPY_FILE allowed only in source file signature");
+ return false;
}
}
+
// make sure the binary directory exists
- cmSystemTools::MakeDirectory(this->BinaryDirectory);
+ if (useUniqueBinaryDirectory) {
+ this->BinaryDirectory =
+ cmStrCat(this->Makefile->GetHomeOutputDirectory(),
+ "/CMakeFiles/CMakeScratch/TryCompile-XXXXXX");
+ cmSystemTools::MakeTempDirectory(this->BinaryDirectory);
+ } else {
+ cmSystemTools::MakeDirectory(this->BinaryDirectory);
+ }
// do not allow recursive try Compiles
if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory()) {
@@ -474,7 +460,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
e << "Attempt at a recursive or nested TRY_COMPILE in directory\n"
<< " " << this->BinaryDirectory << "\n";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return -1;
+ return false;
}
std::string outFileName = this->BinaryDirectory + "/CMakeLists.txt";
@@ -485,9 +471,63 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmSystemTools::RemoveFile(ccFile);
// Choose sources.
- if (!useSources) {
- sources.emplace_back(argv[2]);
+ std::vector<std::string> sources;
+ if (arguments.Sources) {
+ sources = std::move(*arguments.Sources);
+ } else if (arguments.SourceDirectoryOrFile) {
+ sources.emplace_back(*arguments.SourceDirectoryOrFile);
+ }
+ if (arguments.SourceFromContent) {
+ auto const k = arguments.SourceFromContent->size();
+ for (auto i = decltype(k){ 0 }; i < k; i += 2) {
+ const auto& name = (*arguments.SourceFromContent)[i + 0];
+ const auto& content = (*arguments.SourceFromContent)[i + 1];
+ auto out = this->WriteSource(name, content, "SOURCE_FROM_CONTENT");
+ if (out.empty()) {
+ return false;
+ }
+ sources.emplace_back(std::move(out));
+ }
+ }
+ if (arguments.SourceFromVar) {
+ auto const k = arguments.SourceFromVar->size();
+ for (auto i = decltype(k){ 0 }; i < k; i += 2) {
+ const auto& name = (*arguments.SourceFromVar)[i + 0];
+ const auto& var = (*arguments.SourceFromVar)[i + 1];
+ const auto& content = this->Makefile->GetDefinition(var);
+ auto out = this->WriteSource(name, content, "SOURCE_FROM_VAR");
+ if (out.empty()) {
+ return false;
+ }
+ sources.emplace_back(std::move(out));
+ }
}
+ if (arguments.SourceFromFile) {
+ auto const k = arguments.SourceFromFile->size();
+ for (auto i = decltype(k){ 0 }; i < k; i += 2) {
+ const auto& dst = (*arguments.SourceFromFile)[i + 0];
+ const auto& src = (*arguments.SourceFromFile)[i + 1];
+
+ if (!cmSystemTools::GetFilenamePath(dst).empty()) {
+ const auto& msg =
+ cmStrCat("SOURCE_FROM_FILE given invalid filename \"", dst, "\"");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return false;
+ }
+
+ auto dstPath = cmStrCat(this->BinaryDirectory, "/", dst);
+ auto const result = cmSystemTools::CopyFileAlways(src, dstPath);
+ if (!result.IsSuccess()) {
+ const auto& msg = cmStrCat("SOURCE_FROM_FILE failed to copy \"", src,
+ "\": ", result.GetString());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return false;
+ }
+
+ sources.emplace_back(std::move(dstPath));
+ }
+ }
+ // TODO: ensure sources is not empty
// Detect languages to enable.
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
@@ -508,7 +548,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
err << cmJoin(langs, " ");
err << "\nSee project() command to enable other languages.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err.str());
- return -1;
+ return false;
}
}
@@ -535,7 +575,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
<< cmSystemTools::GetLastSystemError();
/* clang-format on */
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return -1;
+ return false;
}
cmValue def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
@@ -575,6 +615,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
*cmp0123 == "NEW"_s ? "NEW" : "OLD");
}
+ /* Set MSVC debug information format policy to match our selection. */
+ if (cmValue msvcDebugInformationFormatDefault =
+ this->Makefile->GetDefinition(
+ kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)) {
+ fprintf(fout, "cmake_policy(SET CMP0141 %s)\n",
+ !msvcDebugInformationFormatDefault->empty() ? "NEW" : "OLD");
+ }
+
/* Set cache/normal variable policy to match outer project.
It may affect toolchain files. */
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) !=
@@ -604,13 +652,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
- if (cmakeInternal == "ABI") {
+ if (arguments.CMakeInternal == "ABI") {
// This is the ABI detection step, also used for implicit includes.
// Erase any include_directories() calls from the toolchain file so
// that we do not see them as implicit. Our ABI detection source
// does not include any system headers anyway.
fprintf(fout,
"set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n");
+
+ // The link and compile lines for ABI detection step need to not use
+ // response files so we can extract implicit includes given to
+ // the underlying host compiler
+ if (testLangs.find("CUDA") != testLangs.end()) {
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES OFF)\n");
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)\n");
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS OFF)\n");
+ }
}
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
for (std::string const& li : testLangs) {
@@ -702,18 +759,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, "set(CMAKE_SUPPRESS_REGENERATION 1)\n");
fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n");
// handle any compile flags we need to pass on
- if (!compileDefs.empty()) {
+ if (!arguments.CompileDefs.empty()) {
// Pass using bracket arguments to preserve content.
fprintf(fout, "add_definitions([==[%s]==])\n",
- cmJoin(compileDefs, "]==] [==[").c_str());
+ cmJoin(arguments.CompileDefs, "]==] [==[").c_str());
}
- /* Use a random file name to avoid rapid creation and deletion
- of the same executable name (some filesystems fail on that). */
- snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
- cmSystemTools::RandomSeed() & 0xFFFFF);
- targetName = targetNameBuf;
-
if (!targets.empty()) {
std::string fname = "/" + std::string(targetName) + "Targets.cmake";
cmExportTryCompileFileGenerator tcfg(gg, targets, this->Makefile,
@@ -725,7 +776,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"could not write export file.");
fclose(fout);
- return -1;
+ return false;
}
fprintf(fout, "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n",
fname.c_str());
@@ -769,24 +820,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, " \"%s\"", si.c_str());
// Add dependencies on any non-temporary sources.
- if (si.find("CMakeTmp") == std::string::npos) {
+ if (!IsTemporary(si)) {
this->Makefile->AddCMakeDependFile(si);
}
}
fprintf(fout, ")\n");
- cState.Enabled(testLangs.find("C") != testLangs.end());
- cxxState.Enabled(testLangs.find("CXX") != testLangs.end());
- cudaState.Enabled(testLangs.find("CUDA") != testLangs.end());
- hipState.Enabled(testLangs.find("HIP") != testLangs.end());
- objcState.Enabled(testLangs.find("OBJC") != testLangs.end());
- objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end());
+ /* Write out the output location of the target we are building */
+ std::string perConfigGenex;
+ if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) {
+ perConfigGenex = "_$<UPPER_CASE:$<CONFIG>>";
+ }
+ fprintf(fout,
+ "file(GENERATE OUTPUT "
+ "\"${CMAKE_BINARY_DIR}/%s%s_loc\"\n",
+ targetName.c_str(), perConfigGenex.c_str());
+ fprintf(fout, " CONTENT $<TARGET_FILE:%s>)\n", targetName.c_str());
bool warnCMP0067 = false;
bool honorStandard = true;
- if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() &&
- objcxxState.DidNone() && cudaState.DidNone() && hipState.DidNone()) {
+ if (arguments.LangProps.empty()) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -811,18 +865,33 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::vector<std::string> warnCMP0067Variables;
- cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067,
- warnCMP0067Variables);
- cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- hipState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
+ if (honorStandard || warnCMP0067) {
+ static std::array<std::string, 6> const possibleLangs{
+ { "C", "CXX", "CUDA", "HIP", "OBJC", "OBJCXX" }
+ };
+ static std::array<cm::string_view, 3> const langPropSuffixes{
+ { "_STANDARD"_s, "_STANDARD_REQUIRED"_s, "_EXTENSIONS"_s }
+ };
+ for (std::string const& lang : possibleLangs) {
+ if (testLangs.find(lang) == testLangs.end()) {
+ continue;
+ }
+ for (cm::string_view propSuffix : langPropSuffixes) {
+ std::string langProp = cmStrCat(lang, propSuffix);
+ if (!arguments.LangProps.count(langProp)) {
+ std::string langPropVar = cmStrCat("CMAKE_"_s, langProp);
+ std::string value = this->Makefile->GetSafeDefinition(langPropVar);
+ if (warnCMP0067 && !value.empty()) {
+ value.clear();
+ warnCMP0067Variables.emplace_back(langPropVar);
+ }
+ if (!value.empty()) {
+ arguments.LangProps[langProp] = value;
+ }
+ }
+ }
+ }
+ }
if (!warnCMP0067Variables.empty()) {
std::ostringstream w;
@@ -838,17 +907,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- cState.WriteProperties(fout, targetName);
- cxxState.WriteProperties(fout, targetName);
- cudaState.WriteProperties(fout, targetName);
- hipState.WriteProperties(fout, targetName);
- objcState.WriteProperties(fout, targetName);
- objcxxState.WriteProperties(fout, targetName);
+ for (auto const& p : arguments.LangProps) {
+ if (p.second.empty()) {
+ continue;
+ }
+ fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
+ targetName.c_str(),
+ cmOutputConverter::EscapeForCMake(p.first).c_str(),
+ cmOutputConverter::EscapeForCMake(p.second).c_str());
+ }
- if (!linkOptions.empty()) {
+ if (!arguments.LinkOptions.empty()) {
std::vector<std::string> options;
- options.reserve(linkOptions.size());
- for (const auto& option : linkOptions) {
+ options.reserve(arguments.LinkOptions.size());
+ for (const auto& option : arguments.LinkOptions) {
options.emplace_back(cmOutputConverter::EscapeForCMake(option));
}
@@ -862,15 +934,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- if (useOldLinkLibs) {
- fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
- targetName.c_str());
- } else {
+ if (arguments.LinkLibraries) {
+ std::string libsToLink = " ";
+ for (std::string const& i : *arguments.LinkLibraries) {
+ libsToLink += "\"" + cmTrimWhitespace(i) + "\" ";
+ }
fprintf(fout, "target_link_libraries(%s %s)\n", targetName.c_str(),
libsToLink.c_str());
+ } else {
+ fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
+ targetName.c_str());
}
fclose(fout);
- projectName = "CMAKE_TRY_COMPILE";
}
// Forward a set of variables to the inner project cache.
@@ -917,6 +992,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_WARN_DEPRECATED);
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
+ vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
if (cmValue varListStr = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
@@ -959,13 +1035,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) {
vars.erase(kCMAKE_OSX_ARCHITECTURES);
std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs;
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
for (std::string const& var : vars) {
if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + *val;
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
}
}
@@ -975,37 +1051,50 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
for (std::string const& var : ghs_platform_vars) {
if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + "'" + *val + "'";
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
}
}
+ if (this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
+ auto msg =
+ cmStrCat("Executing try_compile (", *arguments.CompileResultVariable,
+ ") in:\n ", this->BinaryDirectory);
+ this->Makefile->IssueMessage(MessageType::LOG, msg);
+ }
+
bool erroroc = cmSystemTools::GetErrorOccurredFlag();
cmSystemTools::ResetErrorOccurredFlag();
std::string output;
// actually do the try compile now that everything is setup
int res = this->Makefile->TryCompile(
sourceDirectory, this->BinaryDirectory, projectName, targetName,
- this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,
- output);
+ this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL,
+ &arguments.CMakeFlags, output);
if (erroroc) {
cmSystemTools::SetErrorOccurred();
}
// set the result var to the return value to indicate success or failure
- this->Makefile->AddCacheDefinition(argv[0], (res == 0 ? "TRUE" : "FALSE"),
- "Result of TRY_COMPILE",
- cmStateEnums::INTERNAL);
+ if (arguments.NoCache) {
+ this->Makefile->AddDefinition(*arguments.CompileResultVariable,
+ (res == 0 ? "TRUE" : "FALSE"));
+ } else {
+ this->Makefile->AddCacheDefinition(
+ *arguments.CompileResultVariable, (res == 0 ? "TRUE" : "FALSE"),
+ "Result of TRY_COMPILE", cmStateEnums::INTERNAL);
+ }
- if (!outputVariable.empty()) {
- this->Makefile->AddDefinition(outputVariable, output);
+ if (arguments.OutputVariable) {
+ this->Makefile->AddDefinition(*arguments.OutputVariable, output);
}
if (this->SrcFileSignature) {
std::string copyFileErrorMessage;
- this->FindOutputFile(targetName, targetType);
+ this->FindOutputFile(targetName);
- if ((res == 0) && !copyFile.empty()) {
+ if ((res == 0) && arguments.CopyFileTo) {
+ std::string const& copyFile = *arguments.CopyFileTo;
if (this->OutputFile.empty() ||
!cmSystemTools::CopyFileAlways(this->OutputFile, copyFile)) {
std::ostringstream emsg;
@@ -1018,19 +1107,26 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (!this->FindErrorMessage.empty()) {
emsg << this->FindErrorMessage;
}
- if (copyFileError.empty()) {
+ if (!arguments.CopyFileError) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str());
- return -1;
+ return false;
}
copyFileErrorMessage = emsg.str();
}
}
- if (!copyFileError.empty()) {
+ if (arguments.CopyFileError) {
+ std::string const& copyFileError = *arguments.CopyFileError;
this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage);
}
}
- return res;
+ return res == 0;
+}
+
+bool cmCoreTryCompile::IsTemporary(std::string const& path)
+{
+ return ((path.find("CMakeTmp") != std::string::npos) ||
+ (path.find("CMakeScratch") != std::string::npos));
}
void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
@@ -1039,11 +1135,11 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
return;
}
- if (binDir.find("CMakeTmp") == std::string::npos) {
+ if (!IsTemporary(binDir)) {
cmSystemTools::Error(
"TRY_COMPILE attempt to remove -rf directory that does not contain "
- "CMakeTmp:" +
- binDir);
+ "CMakeTmp or CMakeScratch: \"" +
+ binDir + "\"");
return;
}
@@ -1089,63 +1185,74 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
}
}
}
+
+ if (binDir.find("CMakeScratch") != std::string::npos) {
+ cmSystemTools::RemoveADirectory(binDir);
+ }
}
-void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
- cmStateEnums::TargetType targetType)
+void cmCoreTryCompile::FindOutputFile(const std::string& targetName)
{
this->FindErrorMessage.clear();
this->OutputFile.clear();
std::string tmpOutputFile = "/";
- if (targetType == cmStateEnums::EXECUTABLE) {
- tmpOutputFile += targetName;
- tmpOutputFile +=
- this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
- } else // if (targetType == cmStateEnums::STATIC_LIBRARY)
- {
- tmpOutputFile +=
- this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
- tmpOutputFile += targetName;
- tmpOutputFile +=
- this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
+ tmpOutputFile += targetName;
+
+ if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) {
+ tmpOutputFile += "_DEBUG";
+ }
+ tmpOutputFile += "_loc";
+
+ std::string command = cmStrCat(this->BinaryDirectory, tmpOutputFile);
+ if (!cmSystemTools::FileExists(command)) {
+ std::ostringstream emsg;
+ emsg << "Unable to find the recorded try_compile output location:\n";
+ emsg << cmStrCat(" ", command, "\n");
+ this->FindErrorMessage = emsg.str();
+ return;
+ }
+
+ std::string outputFileLocation;
+ cmsys::ifstream ifs(command.c_str());
+ cmSystemTools::GetLineFromStream(ifs, outputFileLocation);
+ if (!cmSystemTools::FileExists(outputFileLocation)) {
+ std::ostringstream emsg;
+ emsg << "Recorded try_compile output location doesn't exist:\n";
+ emsg << cmStrCat(" ", outputFileLocation, "\n");
+ this->FindErrorMessage = emsg.str();
+ return;
}
- // a list of directories where to search for the compilation result
- // at first directly in the binary dir
- std::vector<std::string> searchDirs;
- searchDirs.emplace_back();
-
- cmValue config =
- this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
- // if a config was specified try that first
- if (cmNonempty(config)) {
- std::string tmp = cmStrCat('/', *config);
- searchDirs.emplace_back(std::move(tmp));
+ this->OutputFile = cmSystemTools::CollapseFullPath(outputFileLocation);
+}
+
+std::string cmCoreTryCompile::WriteSource(std::string const& filename,
+ std::string const& content,
+ char const* command) const
+{
+ if (!cmSystemTools::GetFilenamePath(filename).empty()) {
+ const auto& msg =
+ cmStrCat(command, " given invalid filename \"", filename, "\"");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return {};
}
- searchDirs.emplace_back("/Debug");
-#if defined(__APPLE__)
- std::string app = "/" + targetName + ".app";
- if (cmNonempty(config)) {
- std::string tmp = cmStrCat('/', *config, app);
- searchDirs.emplace_back(std::move(tmp));
+
+ auto filepath = cmStrCat(this->BinaryDirectory, "/", filename);
+ cmsys::ofstream file{ filepath.c_str(), std::ios::out };
+ if (!file) {
+ const auto& msg =
+ cmStrCat(command, " failed to open \"", filename, "\" for writing");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return {};
}
- std::string tmp = "/Debug" + app;
- searchDirs.emplace_back(std::move(tmp));
- searchDirs.emplace_back(std::move(app));
-#endif
- searchDirs.emplace_back("/Development");
- for (std::string const& sdir : searchDirs) {
- std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile);
- if (cmSystemTools::FileExists(command)) {
- this->OutputFile = cmSystemTools::CollapseFullPath(command);
- return;
- }
+ file << content;
+ if (!file) {
+ const auto& msg = cmStrCat(command, " failed to write \"", filename, "\"");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return {};
}
- std::ostringstream emsg;
- emsg << "Unable to find the executable at any of:\n";
- emsg << cmWrap(" " + this->BinaryDirectory, searchDirs, tmpOutputFile, "\n")
- << "\n";
- this->FindErrorMessage = emsg.str();
+ file.close();
+ return filepath;
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 594fd7f9f..3e1e12ca3 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -4,28 +4,90 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
#include <string>
#include <vector>
-#include "cmCommand.h"
+#include <cm/optional>
+
+#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmStateTypes.h"
+class cmMakefile;
+template <typename Iter>
+class cmRange;
+
/** \class cmCoreTryCompile
* \brief Base class for cmTryCompileCommand and cmTryRunCommand
*
* cmCoreTryCompile implements the functionality to build a program.
* It is the base class for cmTryCompileCommand and cmTryRunCommand.
*/
-class cmCoreTryCompile : public cmCommand
+class cmCoreTryCompile
{
public:
-protected:
+ cmCoreTryCompile(cmMakefile* mf)
+ : Makefile(mf)
+ {
+ }
+
+ struct Arguments : public ArgumentParser::ParseResult
+ {
+ cm::optional<std::string> CompileResultVariable;
+ cm::optional<std::string> BinaryDirectory;
+ cm::optional<std::string> SourceDirectoryOrFile;
+ cm::optional<std::string> ProjectName;
+ cm::optional<std::string> TargetName;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> Sources;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ SourceFromContent;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ SourceFromVar;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ SourceFromFile;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{
+ 1, "CMAKE_FLAGS"
+ }; // fake argv[0]
+ std::vector<std::string> CompileDefs;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>>
+ LinkLibraries;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> LinkOptions;
+ std::map<std::string, std::string> LangProps;
+ std::string CMakeInternal;
+ cm::optional<std::string> OutputVariable;
+ cm::optional<std::string> CopyFileTo;
+ cm::optional<std::string> CopyFileError;
+ bool NoCache = false;
+
+ // Argument for try_run only.
+ // Keep in sync with warnings in cmCoreTryCompile::ParseArgs.
+ cm::optional<std::string> CompileOutputVariable;
+ cm::optional<std::string> RunOutputVariable;
+ cm::optional<std::string> RunOutputStdOutVariable;
+ cm::optional<std::string> RunOutputStdErrVariable;
+ cm::optional<std::string> RunWorkingDirectory;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> RunArgs;
+ };
+
+ Arguments ParseArgs(cmRange<std::vector<std::string>::const_iterator> args,
+ bool isTryRun);
+
/**
- * This is the core code for try compile. It is here so that other
- * commands, such as TryRun can access the same logic without
- * duplication.
+ * This is the core code for try compile. It is here so that other commands,
+ * such as TryRun can access the same logic without duplication.
+ *
+ * This function requires at least two \p arguments and will crash if given
+ * fewer.
*/
- int TryCompileCode(std::vector<std::string> const& argv, bool isTryRun);
+ bool TryCompileCode(Arguments& arguments,
+ cmStateEnums::TargetType targetType);
+
+ /**
+ * Returns \c true if \p path resides within a CMake temporary directory,
+ * otherwise returns \c false.
+ */
+ static bool IsTemporary(std::string const& path);
/**
* This deletes all the files created by TryCompileCode.
@@ -39,11 +101,20 @@ protected:
TryCompileCode. The result is stored in OutputFile. If nothing is found,
the error message is stored in FindErrorMessage.
*/
- void FindOutputFile(const std::string& targetName,
- cmStateEnums::TargetType targetType);
+ void FindOutputFile(const std::string& targetName);
std::string BinaryDirectory;
std::string OutputFile;
std::string FindErrorMessage;
bool SrcFileSignature = false;
+ cmMakefile* Makefile;
+
+private:
+ std::string WriteSource(std::string const& name, std::string const& content,
+ char const* command) const;
+
+ Arguments ParseArgs(
+ const cmRange<std::vector<std::string>::const_iterator>& args,
+ const cmArgumentParser<Arguments>& parser,
+ std::vector<std::string>& unparsedArguments);
};
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 2a52d1abd..75c25e3d5 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -87,9 +87,7 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
}
cmSystemTools::ConvertToUnixSlashes(func_name);
- std::replace(func_name.begin(), func_name.end(), ' ', '_');
- std::replace(func_name.begin(), func_name.end(), '/', '_');
- std::replace(func_name.begin(), func_name.end(), ':', '_');
+ func_name = cmSystemTools::MakeCidentifier(func_name);
bool already_declared =
std::find(tests_func_name.begin(), tests_func_name.end(), func_name) !=
tests_func_name.end();
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 28ee24dfe..fd6aee1f3 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -34,10 +34,21 @@
std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile)
{
std::string e;
+ std::string env_ca;
if (!cafile.empty()) {
::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile.c_str());
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
+ /* Honor the user-configurable OpenSSL environment variables. */
+ else if (cmSystemTools::GetEnv("SSL_CERT_FILE", env_ca) &&
+ cmSystemTools::FileExists(env_ca, true)) {
+ ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, env_ca.c_str());
+ check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
+ } else if (cmSystemTools::GetEnv("SSL_CERT_DIR", env_ca) &&
+ cmSystemTools::FileIsDirectory(env_ca)) {
+ ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAPATH, env_ca.c_str());
+ check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
+ }
#ifdef CMAKE_FIND_CAFILE
# define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt"
else if (cmSystemTools::FileExists(CMAKE_CAFILE_FEDORA, true)) {
diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx
new file mode 100644
index 000000000..84691c9fc
--- /dev/null
+++ b/Source/cmCxxModuleMapper.cxx
@@ -0,0 +1,308 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCxxModuleMapper.h"
+
+#include <cassert>
+#include <cstddef>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmScanDepFormat.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+cm::optional<std::string> CxxModuleLocations::BmiGeneratorPathForModule(
+ std::string const& logical_name) const
+{
+ if (auto l = this->BmiLocationForModule(logical_name)) {
+ return this->PathForGenerator(*l);
+ }
+ return {};
+}
+
+namespace {
+
+std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj)
+{
+ std::stringstream mm;
+
+ // Documented in GCC's documentation. The format is a series of
+ // lines with a module name and the associated filename separated
+ // by spaces. The first line may use `$root` as the module name
+ // to specify a "repository root". That is used to anchor any
+ // relative paths present in the file (CMake should never
+ // generate any).
+
+ // Write the root directory to use for module paths.
+ mm << "$root " << loc.RootDirectory << "\n";
+
+ for (auto const& p : obj.Provides) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) {
+ mm << p.LogicalName << ' ' << *bmi_loc << '\n';
+ }
+ }
+ for (auto const& r : obj.Requires) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) {
+ mm << r.LogicalName << ' ' << *bmi_loc << '\n';
+ }
+ }
+
+ return mm.str();
+}
+
+std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj,
+ CxxModuleUsage const& usages)
+{
+ std::stringstream mm;
+
+ // A response file of `-reference NAME=PATH` arguments.
+
+ // MSVC's command line only supports a single output. If more than one is
+ // expected, we cannot make a useful module map file.
+ if (obj.Provides.size() > 1) {
+ return {};
+ }
+
+ auto flag_for_method = [](LookupMethod method) -> cm::static_string_view {
+ switch (method) {
+ case LookupMethod::ByName:
+ return "-reference"_s;
+ case LookupMethod::IncludeAngle:
+ return "-headerUnit:angle"_s;
+ case LookupMethod::IncludeQuote:
+ return "-headerUnit:quote"_s;
+ }
+ assert(false && "unsupported lookup method");
+ return ""_s;
+ };
+
+ for (auto const& p : obj.Provides) {
+ if (p.IsInterface) {
+ mm << "-interface\n";
+ } else {
+ mm << "-internalPartition\n";
+ }
+
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) {
+ mm << "-ifcOutput " << *bmi_loc << '\n';
+ }
+ }
+
+ std::set<std::string> transitive_usage_directs;
+ std::set<std::string> transitive_usage_names;
+
+ for (auto const& r : obj.Requires) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) {
+ auto flag = flag_for_method(r.Method);
+
+ mm << flag << ' ' << r.LogicalName << '=' << *bmi_loc << "\n";
+ transitive_usage_directs.insert(r.LogicalName);
+
+ // Insert transitive usages.
+ auto transitive_usages = usages.Usage.find(r.LogicalName);
+ if (transitive_usages != usages.Usage.end()) {
+ transitive_usage_names.insert(transitive_usages->second.begin(),
+ transitive_usages->second.end());
+ }
+ }
+ }
+
+ for (auto const& transitive_name : transitive_usage_names) {
+ if (transitive_usage_directs.count(transitive_name)) {
+ continue;
+ }
+
+ auto module_ref = usages.Reference.find(transitive_name);
+ if (module_ref != usages.Reference.end()) {
+ auto flag = flag_for_method(module_ref->second.Method);
+ mm << flag << ' ' << transitive_name << '=' << module_ref->second.Path
+ << "\n";
+ }
+ }
+
+ return mm.str();
+}
+}
+
+bool CxxModuleUsage::AddReference(std::string const& logical,
+ std::string const& loc, LookupMethod method)
+{
+ auto r = this->Reference.find(logical);
+ if (r != this->Reference.end()) {
+ auto& ref = r->second;
+
+ if (ref.Path == loc && ref.Method == method) {
+ return true;
+ }
+
+ auto method_name = [](LookupMethod m) -> cm::static_string_view {
+ switch (m) {
+ case LookupMethod::ByName:
+ return "by-name"_s;
+ case LookupMethod::IncludeAngle:
+ return "include-angle"_s;
+ case LookupMethod::IncludeQuote:
+ return "include-quote"_s;
+ }
+ assert(false && "unsupported lookup method");
+ return ""_s;
+ };
+
+ cmSystemTools::Error(cmStrCat("Disagreement of the location of the '",
+ logical,
+ "' module. "
+ "Location A: '",
+ ref.Path, "' via ", method_name(ref.Method),
+ "; "
+ "Location B: '",
+ loc, "' via ", method_name(method), "."));
+ return false;
+ }
+
+ auto& ref = this->Reference[logical];
+ ref.Path = loc;
+ ref.Method = method;
+
+ return true;
+}
+
+cm::static_string_view CxxModuleMapExtension(
+ cm::optional<CxxModuleMapFormat> format)
+{
+ if (format) {
+ switch (*format) {
+ case CxxModuleMapFormat::Gcc:
+ return ".gcm"_s;
+ case CxxModuleMapFormat::Msvc:
+ return ".ifc"_s;
+ }
+ }
+
+ return ".bmi"_s;
+}
+
+std::set<std::string> CxxModuleUsageSeed(
+ CxxModuleLocations const& loc, std::vector<cmScanDepInfo> const& objects,
+ CxxModuleUsage& usages)
+{
+ // Track inner usages to populate usages from internal bits.
+ //
+ // This is a map of modules that required some other module that was not
+ // found to those that were not found.
+ std::map<std::string, std::set<std::string>> internal_usages;
+ std::set<std::string> unresolved;
+
+ for (cmScanDepInfo const& object : objects) {
+ // Add references for each of the provided modules.
+ for (auto const& p : object.Provides) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) {
+ // XXX(cxx-modules): How to support header units?
+ usages.AddReference(p.LogicalName, loc.PathForGenerator(*bmi_loc),
+ LookupMethod::ByName);
+ }
+ }
+
+ // For each requires, pull in what is required.
+ for (auto const& r : object.Requires) {
+ // Find transitive usages.
+ auto transitive_usages = usages.Usage.find(r.LogicalName);
+ // Find the required name in the current target.
+ auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName);
+
+ for (auto const& p : object.Provides) {
+ auto& this_usages = usages.Usage[p.LogicalName];
+
+ // Add the direct usage.
+ this_usages.insert(r.LogicalName);
+
+ // Add the transitive usage.
+ if (transitive_usages != usages.Usage.end()) {
+ this_usages.insert(transitive_usages->second.begin(),
+ transitive_usages->second.end());
+ } else if (bmi_loc) {
+ // Mark that we need to update transitive usages later.
+ internal_usages[p.LogicalName].insert(r.LogicalName);
+ }
+ }
+
+ if (bmi_loc) {
+ usages.AddReference(r.LogicalName, loc.PathForGenerator(*bmi_loc),
+ r.Method);
+ }
+ }
+ }
+
+ // While we have internal usages to manage.
+ while (!internal_usages.empty()) {
+ size_t starting_size = internal_usages.size();
+
+ // For each internal usage.
+ for (auto usage = internal_usages.begin(); usage != internal_usages.end();
+ /* see end of loop */) {
+ auto& this_usages = usages.Usage[usage->first];
+
+ for (auto use = usage->second.begin(); use != usage->second.end();
+ /* see end of loop */) {
+ // Check if this required module uses other internal modules; defer
+ // if so.
+ if (internal_usages.count(*use)) {
+ // Advance the iterator.
+ ++use;
+ continue;
+ }
+
+ auto transitive_usages = usages.Usage.find(*use);
+ if (transitive_usages != usages.Usage.end()) {
+ this_usages.insert(transitive_usages->second.begin(),
+ transitive_usages->second.end());
+ }
+
+ // Remove the entry and advance the iterator.
+ use = usage->second.erase(use);
+ }
+
+ // Erase the entry if it doesn't have any remaining usages.
+ if (usage->second.empty()) {
+ usage = internal_usages.erase(usage);
+ } else {
+ ++usage;
+ }
+ }
+
+ // Check that at least one usage was resolved.
+ if (starting_size == internal_usages.size()) {
+ // Nothing could be resolved this loop; we have a cycle, so record the
+ // cycle and exit.
+ for (auto const& usage : internal_usages) {
+ unresolved.insert(usage.first);
+ }
+ break;
+ }
+ }
+
+ return unresolved;
+}
+
+std::string CxxModuleMapContent(CxxModuleMapFormat format,
+ CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj,
+ CxxModuleUsage const& usages)
+{
+ switch (format) {
+ case CxxModuleMapFormat::Gcc:
+ return CxxModuleMapContentGcc(loc, obj);
+ case CxxModuleMapFormat::Msvc:
+ return CxxModuleMapContentMsvc(loc, obj, usages);
+ }
+
+ assert(false);
+ return {};
+}
diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h
new file mode 100644
index 000000000..8526a0750
--- /dev/null
+++ b/Source/cmCxxModuleMapper.h
@@ -0,0 +1,85 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <functional>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include "cmScanDepFormat.h"
+
+enum class CxxModuleMapFormat
+{
+ Gcc,
+ Msvc,
+};
+
+struct CxxModuleLocations
+{
+ // The path from which all relative paths should be computed. If
+ // this is relative, it is relative to the compiler's working
+ // directory.
+ std::string RootDirectory;
+
+ // A function to convert a full path to a path for the generator.
+ std::function<std::string(std::string const&)> PathForGenerator;
+
+ // Lookup the BMI location of a logical module name.
+ std::function<cm::optional<std::string>(std::string const&)>
+ BmiLocationForModule;
+
+ // Returns the generator path (if known) for the BMI given a
+ // logical module name.
+ cm::optional<std::string> BmiGeneratorPathForModule(
+ std::string const& logical_name) const;
+};
+
+struct CxxModuleReference
+{
+ // The path to the module file used.
+ std::string Path;
+ // How the module was looked up.
+ LookupMethod Method;
+};
+
+struct CxxModuleUsage
+{
+ // The usage requirements for this object.
+ std::map<std::string, std::set<std::string>> Usage;
+
+ // The references for this object.
+ std::map<std::string, CxxModuleReference> Reference;
+
+ // Add a reference to a module.
+ //
+ // Returns `true` if it matches how it was found previously, `false` if it
+ // conflicts.
+ bool AddReference(std::string const& logical, std::string const& loc,
+ LookupMethod method);
+};
+
+// Return the extension to use for a given modulemap format.
+cm::static_string_view CxxModuleMapExtension(
+ cm::optional<CxxModuleMapFormat> format);
+
+// Fill in module usage information for internal usages.
+//
+// Returns the set of unresolved module usage requirements (these form an
+// import cycle).
+std::set<std::string> CxxModuleUsageSeed(
+ CxxModuleLocations const& loc, std::vector<cmScanDepInfo> const& objects,
+ CxxModuleUsage& usages);
+
+// Return the contents of the module map in the given format for the
+// object file.
+std::string CxxModuleMapContent(CxxModuleMapFormat format,
+ CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj,
+ CxxModuleUsage const& usages);
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index faefcb8f8..31ee6652f 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -8,6 +8,7 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmProperty.h"
@@ -51,8 +52,8 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
// Parse remaining arguments.
bool inherited = false;
std::string PropertyName;
- std::vector<std::string> BriefDocs;
- std::vector<std::string> FullDocs;
+ ArgumentParser::NonEmpty<std::vector<std::string>> BriefDocs;
+ ArgumentParser::NonEmpty<std::vector<std::string>> FullDocs;
std::string initializeFromVariable;
cmArgumentParser<void> parser;
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index 3619aded5..d466a120e 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -17,30 +17,32 @@
#include "cmVersion.h"
static const char* cmDocumentationStandardOptions[][2] = {
- { "--help,-help,-usage,-h,-H,/?", "Print usage information and exit." },
- { "--version,-version,/V [<f>]", "Print version number and exit." },
- { "--help-full [<f>]", "Print all help manuals and exit." },
- { "--help-manual <man> [<f>]", "Print one help manual and exit." },
- { "--help-manual-list [<f>]", "List help manuals available and exit." },
- { "--help-command <cmd> [<f>]", "Print help for one command and exit." },
- { "--help-command-list [<f>]",
+ { "-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." },
+ { "--help-manual <man> [<file>]", "Print one help manual and exit." },
+ { "--help-manual-list [<file>]", "List help manuals available and exit." },
+ { "--help-command <cmd> [<file>]", "Print help for one command and exit." },
+ { "--help-command-list [<file>]",
"List commands with help available and exit." },
- { "--help-commands [<f>]", "Print cmake-commands manual and exit." },
- { "--help-module <mod> [<f>]", "Print help for one module and exit." },
- { "--help-module-list [<f>]", "List modules with help available and exit." },
- { "--help-modules [<f>]", "Print cmake-modules manual and exit." },
- { "--help-policy <cmp> [<f>]", "Print help for one policy and exit." },
- { "--help-policy-list [<f>]",
+ { "--help-commands [<file>]", "Print cmake-commands manual and exit." },
+ { "--help-module <mod> [<file>]", "Print help for one module and exit." },
+ { "--help-module-list [<file>]",
+ "List modules with help available and exit." },
+ { "--help-modules [<file>]", "Print cmake-modules manual and exit." },
+ { "--help-policy <cmp> [<file>]", "Print help for one policy and exit." },
+ { "--help-policy-list [<file>]",
"List policies with help available and exit." },
- { "--help-policies [<f>]", "Print cmake-policies manual and exit." },
- { "--help-property <prop> [<f>]", "Print help for one property and exit." },
- { "--help-property-list [<f>]",
+ { "--help-policies [<file>]", "Print cmake-policies manual and exit." },
+ { "--help-property <prop> [<file>]",
+ "Print help for one property and exit." },
+ { "--help-property-list [<file>]",
"List properties with help available and exit." },
- { "--help-properties [<f>]", "Print cmake-properties manual and exit." },
- { "--help-variable var [<f>]", "Print help for one variable and exit." },
- { "--help-variable-list [<f>]",
+ { "--help-properties [<file>]", "Print cmake-properties manual and exit." },
+ { "--help-variable var [<file>]", "Print help for one variable and exit." },
+ { "--help-variable-list [<file>]",
"List variables with help available and exit." },
- { "--help-variables [<f>]", "Print cmake-variables manual and exit." },
+ { "--help-variables [<file>]", "Print cmake-variables manual and exit." },
{ nullptr, nullptr }
};
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 222ea80a5..7fbd82690 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -47,7 +47,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::vector<std::vector<std::string>> Commands;
std::string OutputVariable;
@@ -95,14 +95,10 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args, &unparsedArguments);
- if (!keywordsMissingValue.empty()) {
- status.SetError(" called with no value for " +
- keywordsMissingValue.front() + ".");
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!unparsedArguments.empty()) {
status.SetError(" given unknown argument \"" + unparsedArguments.front() +
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index 0feaedf33..ced354811 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -5,6 +5,7 @@
#include <cmConfigure.h> // IWYU pragma: keep
#include <string>
+#include <vector>
class cmMakefile;
@@ -27,8 +28,21 @@ public:
void SetError(std::string const& e) { this->Error = e; }
std::string const& GetError() const { return this->Error; }
- void SetReturnInvoked() { this->ReturnInvoked = true; }
+ void SetReturnInvoked()
+ {
+ this->Variables.clear();
+ this->ReturnInvoked = true;
+ }
+ void SetReturnInvoked(std::vector<std::string> variables)
+ {
+ this->Variables = std::move(variables);
+ this->ReturnInvoked = true;
+ }
bool GetReturnInvoked() const { return this->ReturnInvoked; }
+ const std::vector<std::string>& GetReturnVariables() const
+ {
+ return this->Variables;
+ }
void SetBreakInvoked() { this->BreakInvoked = true; }
bool GetBreakInvoked() const { return this->BreakInvoked; }
@@ -46,4 +60,5 @@ private:
bool BreakInvoked = false;
bool ContinueInvoked = false;
bool NestedError = false;
+ std::vector<std::string> Variables;
};
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx
new file mode 100644
index 000000000..922b53fd1
--- /dev/null
+++ b/Source/cmExperimental.cxx
@@ -0,0 +1,63 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmExperimental.h"
+
+#include <cassert>
+#include <cstddef>
+#include <string>
+
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmValue.h"
+
+namespace {
+
+/*
+ * The `Uuid` fields of these objects should change periodically.
+ * Search for other instances to keep the documentation and test suite
+ * up-to-date.
+ */
+
+struct FeatureData
+{
+ std::string const Uuid;
+ std::string const Variable;
+ std::string const Description;
+ bool Warned;
+} LookupTable[] = {
+ // CxxModuleCMakeApi
+ { "3c375311-a3c9-4396-a187-3227ef642046",
+ "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API",
+ "CMake's C++ module support is experimental. It is meant only for "
+ "experimentation and feedback to CMake developers.",
+ false },
+};
+static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) ==
+ static_cast<size_t>(cmExperimental::Feature::Sentinel),
+ "Experimental feature lookup table mismatch");
+
+FeatureData& DataForFeature(cmExperimental::Feature f)
+{
+ assert(f != cmExperimental::Feature::Sentinel);
+ return LookupTable[static_cast<size_t>(f)];
+}
+}
+
+bool cmExperimental::HasSupportEnabled(cmMakefile const& mf, Feature f)
+{
+ bool enabled = false;
+ auto& data = DataForFeature(f);
+
+ auto value = mf.GetDefinition(data.Variable);
+ if (value == data.Uuid) {
+ enabled = true;
+ }
+
+ if (enabled && !data.Warned) {
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, data.Description);
+ data.Warned = true;
+ }
+
+ return enabled;
+}
diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h
new file mode 100644
index 000000000..26e0d17db
--- /dev/null
+++ b/Source/cmExperimental.h
@@ -0,0 +1,21 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+class cmMakefile;
+
+class cmExperimental
+{
+public:
+ enum class Feature
+ {
+ CxxModuleCMakeApi,
+
+ Sentinel,
+ };
+
+ static bool HasSupportEnabled(cmMakefile const& mf, Feature f);
+};
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 6ce0c9850..ed199ea5d 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -9,10 +9,13 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmExportSet.h"
#include "cmFileSet.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -23,6 +26,7 @@
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
@@ -139,11 +143,18 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateTargetFileSets(gte, os);
}
+ this->GenerateCxxModuleInformation(os);
+
// Generate import file content for each configuration.
for (std::string const& c : this->Configurations) {
this->GenerateImportConfig(os, c);
}
+ // Generate import file content for each configuration.
+ for (std::string const& c : this->Configurations) {
+ this->GenerateImportCxxModuleConfigTargetInclusion(c);
+ }
+
this->GenerateMissingTargetsCheckCode(os);
return true;
@@ -382,6 +393,21 @@ std::string cmExportBuildFileGenerator::GetFileSetDirectories(
std::any_of(directoryEntries.begin(), directoryEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->LG->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base directory entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& directory : directories) {
auto dest = cmOutputConverter::EscapeForCMake(
directory, cmOutputConverter::WrapQuotes::NoWrap);
@@ -427,6 +453,21 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->LG->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& it : files) {
for (auto const& filename : it.second) {
auto escapedFile = cmOutputConverter::EscapeForCMake(
@@ -447,3 +488,60 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
return cmJoin(resultVector, " ");
}
+
+std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const
+{
+ return this->CxxModulesDirectory;
+}
+
+void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
+ std::ostream& os) const
+{
+ const char* opt = "";
+ if (this->Configurations.size() > 1) {
+ // With more than one configuration, each individual file is optional.
+ opt = " OPTIONAL";
+ }
+
+ // Generate import file content for each configuration.
+ for (std::string c : this->Configurations) {
+ if (c.empty()) {
+ c = "noconfig";
+ }
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\""
+ << opt << ")\n";
+ }
+}
+
+bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
+ std::string config) const
+{
+ auto cxx_modules_dirname = this->GetCxxModulesDirectory();
+ if (cxx_modules_dirname.empty()) {
+ return true;
+ }
+
+ if (config.empty()) {
+ config = "noconfig";
+ }
+
+ std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname,
+ "/cxx-modules-", config, ".cmake");
+
+ cmGeneratedFileStream os(fileName, true);
+ if (!os) {
+ std::string se = cmSystemTools::GetLastSystemError();
+ std::ostringstream e;
+ e << "cannot write to file \"" << fileName << "\": " << se;
+ cmSystemTools::Error(e.str());
+ return false;
+ }
+ os.SetCopyIfDifferent(true);
+
+ for (auto const* tgt : this->ExportedTargets) {
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-" << tgt->GetExportName()
+ << '-' << config << ".cmake\")\n";
+ }
+
+ return true;
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 5681e8fac..4636196c8 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -47,6 +47,16 @@ public:
}
void SetExportSet(cmExportSet*);
+ /** Set the name of the C++ module directory. */
+ void SetCxxModuleDirectory(std::string cxx_module_dir)
+ {
+ this->CxxModulesDirectory = std::move(cxx_module_dir);
+ }
+ const std::string& GetCxxModuleDirectory() const
+ {
+ return this->CxxModulesDirectory;
+ }
+
/** Set whether to append generated code to the output file. */
void SetAppendMode(bool append) { this->AppendMode = append; }
@@ -81,6 +91,10 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override;
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override;
+ bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const;
+
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);
@@ -88,4 +102,6 @@ protected:
cmExportSet* ExportSet;
std::vector<cmGeneratorTarget*> Exports;
cmLocalGenerator* LG;
+ // The directory for C++ module information.
+ std::string CxxModulesDirectory;
};
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 63440a317..a58f2b773 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -7,13 +7,15 @@
#include <utility>
#include <cm/memory>
-#include <cmext/algorithm>
+#include <cm/optional>
#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
+#include "cmExperimental.h"
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportSet.h"
@@ -57,10 +59,11 @@ bool cmExportCommand(std::vector<std::string> const& args,
struct Arguments
{
std::string ExportSetName;
- std::vector<std::string> Targets;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Targets;
std::string Namespace;
std::string Filename;
std::string AndroidMKFile;
+ std::string CxxModulesDirectory;
bool Append = false;
bool ExportOld = false;
};
@@ -69,6 +72,12 @@ bool cmExportCommand(std::vector<std::string> const& args,
.Bind("NAMESPACE"_s, &Arguments::Namespace)
.Bind("FILE"_s, &Arguments::Filename);
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ status.GetMakefile(), cmExperimental::Feature::CxxModuleCMakeApi);
+ if (supportCxx20FileSetTypes) {
+ parser.Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory);
+ }
+
if (args[0] == "EXPORT") {
parser.Bind("EXPORT"_s, &Arguments::ExportSetName);
} else {
@@ -79,9 +88,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
std::vector<std::string> unknownArgs;
- std::vector<std::string> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args, &unknownArgs, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError("Unknown argument: \"" + unknownArgs.front() + "\".");
@@ -145,9 +152,8 @@ bool cmExportCommand(std::vector<std::string> const& args,
return false;
}
exportSet = &it->second;
- } else if (!arguments.Targets.empty() ||
- cm::contains(keywordsMissingValue, "TARGETS")) {
- for (std::string const& currentTarget : arguments.Targets) {
+ } else if (arguments.Targets) {
+ for (std::string const& currentTarget : *arguments.Targets) {
if (mf.IsAlias(currentTarget)) {
std::ostringstream e;
e << "given ALIAS target \"" << currentTarget
@@ -214,6 +220,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
ebfg->SetExportFile(fname.c_str());
ebfg->SetNamespace(arguments.Namespace);
+ ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory);
ebfg->SetAppendMode(arguments.Append);
if (exportSet != nullptr) {
ebfg->SetExportSet(exportSet);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 5a33349b1..50bc78ca5 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -939,13 +939,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.22 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.23 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.8.3...3.22)\n";
+ << "cmake_policy(VERSION 2.8.3...3.23)\n";
/* clang-format on */
}
@@ -1095,6 +1095,10 @@ void cmExportFileGenerator::GenerateImportTargetCode(
<< " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
}
+ if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
+ os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
+ }
+
os << "\n";
}
@@ -1308,3 +1312,28 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
os << " )\nendif()\n\n";
}
}
+
+void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
+{
+ auto const cxx_module_dirname = this->GetCxxModulesDirectory();
+ if (cxx_module_dirname.empty()) {
+ return;
+ }
+
+ // Write the include.
+ os << "# Include C++ module properties\n"
+ << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
+ << "/cxx-modules.cmake\")\n\n";
+
+ // Get the path to the file we're going to write.
+ std::string path = this->MainImportFile;
+ path = cmSystemTools::GetFilenamePath(path);
+ auto trampoline_path =
+ cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake");
+
+ // Include all configuration-specific include files.
+ cmGeneratedFileStream ap(trampoline_path, true);
+ ap.SetCopyIfDifferent(true);
+
+ this->GenerateCxxModuleConfigInformation(ap);
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index d27a55564..fdda878f2 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -182,6 +182,8 @@ protected:
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
cmTargetExport* te = nullptr);
+ void GenerateCxxModuleInformation(std::ostream& os);
+
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
cmTargetExport* te) = 0;
@@ -226,4 +228,7 @@ private:
virtual std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) = 0;
+
+ virtual std::string GetCxxModulesDirectory() const = 0;
+ virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0;
};
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 4e4f8a1e5..d53254df0 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -35,8 +35,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
for (size_t n = 0; n < numDotDot; n++) {
path += "/..";
}
- os << "_IMPORT_PREFIX := "
- << "$(LOCAL_PATH)" << path << "\n\n";
+ os << "_IMPORT_PREFIX := $(LOCAL_PATH)" << path << "\n\n";
for (std::unique_ptr<cmTargetExport> const& te :
this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index adccdfeec..195737b9f 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -7,6 +7,9 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
+#include <cmext/string_view>
+
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
@@ -18,6 +21,7 @@
#include "cmInstallTargetGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -162,10 +166,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->LoadConfigFiles(os);
+ bool result = true;
+
+ this->GenerateCxxModuleInformation(os);
+ if (requiresConfigFiles) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) {
+ result = false;
+ }
+ }
+ }
+
this->CleanupTemporaryVariables(os);
this->GenerateImportedFileCheckLoop(os);
- bool result = true;
// Generate an import file for each configuration.
// Don't do this if we only export INTERFACE_LIBRARY targets.
if (requiresConfigFiles) {
@@ -422,7 +436,10 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
// Append the installed file name.
if (target->IsAppBundleOnApple()) {
value += cmInstallTargetGenerator::GetInstallFilename(target, config);
- value += ".app/Contents/MacOS/";
+ value += ".app/";
+ if (!target->Makefile->PlatformIsAppleEmbedded()) {
+ value += "Contents/MacOS/";
+ }
value += cmInstallTargetGenerator::GetInstallFilename(target, config);
} else {
value += cmInstallTargetGenerator::GetInstallFilename(
@@ -562,6 +579,21 @@ std::string cmExportInstallFileGenerator::GetFileSetDirectories(
cge->Evaluate(gte->LocalGenerator, config, gte),
cmOutputConverter::WrapQuotes::NoWrap));
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (cge->GetHadContextSensitiveCondition() &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
resultVector.push_back(
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
@@ -610,6 +642,21 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles(
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& it : files) {
auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
for (auto const& filename : it.second) {
@@ -635,3 +682,65 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles(
return cmJoin(resultVector, " ");
}
+
+std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
+{
+ return IEGen->GetCxxModuleDirectory();
+}
+
+void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
+ std::ostream& os) const
+{
+ // Now load per-configuration properties for them.
+ /* clang-format off */
+ os << "# Load information for each installed configuration.\n"
+ "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-*.cmake\")\n"
+ "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
+ " include(\"${_cmake_cxx_module_include}\")\n"
+ "endforeach()\n"
+ "unset(_cmake_cxx_module_include)\n"
+ "unset(_cmake_cxx_module_includes)\n";
+ /* clang-format on */
+}
+
+bool cmExportInstallFileGenerator::
+ GenerateImportCxxModuleConfigTargetInclusion(std::string const& config)
+{
+ auto cxx_modules_dirname = this->GetCxxModulesDirectory();
+ if (cxx_modules_dirname.empty()) {
+ return true;
+ }
+
+ std::string filename_config = config;
+ if (filename_config.empty()) {
+ filename_config = "noconfig";
+ }
+
+ std::string const dest =
+ cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
+ std::string fileName =
+ cmStrCat(dest, "cxx-modules-", filename_config, ".cmake");
+
+ cmGeneratedFileStream os(fileName, true);
+ if (!os) {
+ std::string se = cmSystemTools::GetLastSystemError();
+ std::ostringstream e;
+ e << "cannot write to file \"" << fileName << "\": " << se;
+ cmSystemTools::Error(e.str());
+ return false;
+ }
+ os.SetCopyIfDifferent(true);
+
+ // Record this per-config import file.
+ this->ConfigCxxModuleFiles[config] = fileName;
+
+ auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
+ for (auto const* tgt : this->ExportedTargets) {
+ auto prop_filename = cmStrCat("target-", tgt->GetExportName(), '-',
+ filename_config, ".cmake");
+ prop_files.emplace_back(cmStrCat(dest, prop_filename));
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n";
+ }
+
+ return true;
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 86fb505f4..e073a3141 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -50,6 +50,23 @@ public:
return this->ConfigImportFiles;
}
+ /** Get the per-config C++ module file generated for each configuration.
+ This maps from the configuration name to the file temporary location
+ for installation. */
+ std::map<std::string, std::string> const& GetConfigCxxModuleFiles()
+ {
+ return this->ConfigCxxModuleFiles;
+ }
+
+ /** Get the per-config C++ module file generated for each configuration.
+ This maps from the configuration name to the file temporary location
+ for installation for each target in the export set. */
+ std::map<std::string, std::vector<std::string>> const&
+ GetConfigCxxModuleTargetFiles()
+ {
+ return this->ConfigCxxModuleTargetFiles;
+ }
+
/** Compute the globbing expression used to load per-config import
files from the main file. */
std::string GetConfigImportFileGlob();
@@ -100,8 +117,16 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override;
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override;
+ bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&);
+
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.
std::map<std::string, std::string> ConfigImportFiles;
+ // The C++ module property file generated for each configuration.
+ std::map<std::string, std::string> ConfigCxxModuleFiles;
+ // The C++ module property target files generated for each configuration.
+ std::map<std::string, std::vector<std::string>> ConfigCxxModuleTargetFiles;
};
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 1dd8a20a3..5c34fad2f 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -55,6 +55,9 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override { return {}; }
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override {}
+
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index dd0540c48..0581802d5 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -27,6 +27,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -1092,6 +1093,21 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
if (installFileSet->GetOptional()) {
installer["isOptional"] = true;
}
+ } else if (auto* cxxModuleBmi =
+ dynamic_cast<cmInstallCxxModuleBmiGenerator*>(gen)) {
+ installer["type"] = "cxxModuleBmi";
+ installer["destination"] = cxxModuleBmi->GetDestination(this->Config);
+
+ auto const* target = cxxModuleBmi->GetTarget();
+ installer["cxxModuleBmiTarget"] = Json::objectValue;
+ installer["cxxModuleBmiTarget"]["id"] = TargetId(target, this->TopBuild);
+ installer["cxxModuleBmiTarget"]["index"] = this->TargetIndexMap[target];
+
+ // FIXME: Parse FilePermissions.
+ // FIXME: Parse MessageLevel.
+ if (cxxModuleBmi->GetOptional()) {
+ installer["isOptional"] = true;
+ }
}
// Add fields common to all install generators.
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 3c234a69e..fe38db53e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -28,8 +28,8 @@
#include "cm_sys_stat.h"
-#include "cmAlgorithms.h"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmCryptoHash.h"
#include "cmELF.h"
@@ -172,7 +172,8 @@ bool HandleReadCommand(std::vector<std::string> const& args,
.Bind("LIMIT"_s, &Arguments::Limit)
.Bind("HEX"_s, &Arguments::Hex);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3),
+ /*unparsedArguments=*/nullptr);
std::string fileName = fileNameArg;
if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
@@ -959,42 +960,34 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
{
// Evaluate arguments.
std::string file;
- std::string oldRPath;
- std::string newRPath;
+ cm::optional<std::string> oldRPath;
+ cm::optional<std::string> newRPath;
bool removeEnvironmentRPath = false;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
parser.Bind("FILE"_s, file)
.Bind("OLD_RPATH"_s, oldRPath)
.Bind("NEW_RPATH"_s, newRPath)
.Bind("INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, removeEnvironmentRPath);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
- &parsedArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_CHANGE given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_CHANGE \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_CHANGE not given FILE option.");
return false;
}
- if (oldRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "OLD_RPATH") ==
- parsedArgs.end()) {
+ if (!oldRPath) {
status.SetError("RPATH_CHANGE not given OLD_RPATH option.");
return false;
}
- if (newRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") ==
- parsedArgs.end()) {
+ if (!newRPath) {
status.SetError("RPATH_CHANGE not given NEW_RPATH option.");
return false;
}
@@ -1008,17 +1001,17 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
std::string emsg;
bool changed;
- if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath,
+ if (!cmSystemTools::ChangeRPath(file, *oldRPath, *newRPath,
removeEnvironmentRPath, &emsg, &changed)) {
status.SetError(cmStrCat("RPATH_CHANGE could not write new RPATH:\n ",
- newRPath, "\nto the file:\n ", file, "\n",
+ *newRPath, "\nto the file:\n ", file, "\n",
emsg));
success = false;
}
if (success) {
if (changed) {
std::string message =
- cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"');
status.GetMakefile().DisplayStatus(message, -1);
}
ft.Store(file);
@@ -1031,31 +1024,25 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args,
{
// Evaluate arguments.
std::string file;
- std::string newRPath;
+ cm::optional<std::string> newRPath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
parser.Bind("FILE"_s, file).Bind("NEW_RPATH"_s, newRPath);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
- &parsedArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(cmStrCat("RPATH_SET given unrecognized argument \"",
unknownArgs.front(), "\"."));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_SET \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_SET not given FILE option.");
return false;
}
- if (newRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") ==
- parsedArgs.end()) {
+ if (!newRPath) {
status.SetError("RPATH_SET not given NEW_RPATH option.");
return false;
}
@@ -1069,16 +1056,16 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args,
std::string emsg;
bool changed;
- if (!cmSystemTools::SetRPath(file, newRPath, &emsg, &changed)) {
+ if (!cmSystemTools::SetRPath(file, *newRPath, &emsg, &changed)) {
status.SetError(cmStrCat("RPATH_SET could not write new RPATH:\n ",
- newRPath, "\nto the file:\n ", file, "\n",
+ *newRPath, "\nto the file:\n ", file, "\n",
emsg));
success = false;
}
if (success) {
if (changed) {
std::string message =
- cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"');
status.GetMakefile().DisplayStatus(message, -1);
}
ft.Store(file);
@@ -1093,18 +1080,16 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
std::string file;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
parser.Bind("FILE"_s, file);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_REMOVE given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_REMOVE \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_REMOVE not given FILE option.");
@@ -1141,31 +1126,25 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args,
{
// Evaluate arguments.
std::string file;
- std::string rpath;
+ cm::optional<std::string> rpath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
parser.Bind("FILE"_s, file).Bind("RPATH"_s, rpath);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
- &parsedArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_CHECK given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_CHECK \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_CHECK not given FILE option.");
return false;
}
- if (rpath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "RPATH") ==
- parsedArgs.end()) {
+ if (!rpath) {
status.SetError("RPATH_CHECK not given RPATH option.");
return false;
}
@@ -1174,7 +1153,7 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args,
// delete it. This is used during installation to re-install a file
// if its RPath will change.
if (cmSystemTools::FileExists(file, true) &&
- !cmSystemTools::CheckRPath(file, rpath)) {
+ !cmSystemTools::CheckRPath(file, *rpath)) {
cmSystemTools::RemoveFile(file);
}
@@ -1203,7 +1182,8 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
.Bind("RPATH"_s, &Arguments::RPath)
.Bind("RUNPATH"_s, &Arguments::RunPath)
.Bind("CAPTURE_ERROR"_s, &Arguments::Error);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2),
+ /*unparsedArguments=*/nullptr);
if (!cmSystemTools::FileExists(fileNameArg, true)) {
status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
@@ -1256,9 +1236,9 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string BaseDirectory;
+ cm::optional<std::string> BaseDirectory;
bool ExpandTilde = false;
};
static auto const parser =
@@ -1267,22 +1247,18 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
.Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
auto arguments =
- parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments,
- &keywordsMissingValue, &parsedKeywords);
+ parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments);
if (!unparsedArguments.empty()) {
status.SetError("REAL_PATH called with unexpected arguments");
return false;
}
- if (!keywordsMissingValue.empty()) {
- status.SetError("BASE_DIRECTORY requires a value");
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
- if (parsedKeywords.empty()) {
+ if (!arguments.BaseDirectory) {
arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
@@ -1301,7 +1277,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
}
cmCMakePath path(input, cmCMakePath::auto_format);
- path = path.Absolute(arguments.BaseDirectory).Normal();
+ path = path.Absolute(*arguments.BaseDirectory).Normal();
auto realPath = cmSystemTools::GetRealPath(path.GenericString());
status.GetMakefile().AddDefinition(args[2], realPath);
@@ -1944,7 +1920,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
std::string msg;
std::string actualHash = hash->HashFile(file);
if (actualHash == expectedHash) {
- msg = cmStrCat("returning early; file already exists with expected ",
+ msg = cmStrCat("skipping download as file already exists with expected ",
hashMatchMSG, '"');
if (!statusVar.empty()) {
status.GetMakefile().AddDefinition(statusVar, cmStrCat(0, ";\"", msg));
@@ -2114,6 +2090,13 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
::curl_global_cleanup();
+ // Ensure requested curl logs are returned (especially in case of failure)
+ //
+ if (!logVar.empty()) {
+ chunkDebug.push_back(0);
+ status.GetMakefile().AddDefinition(logVar, chunkDebug.data());
+ }
+
// Explicitly flush/close so we can measure the md5 accurately.
//
if (!file.empty()) {
@@ -2156,11 +2139,6 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
}
}
- if (!logVar.empty()) {
- chunkDebug.push_back(0);
- status.GetMakefile().AddDefinition(logVar, chunkDebug.data());
- }
-
return true;
#else
status.SetError("DOWNLOAD not supported by bootstrap cmake.");
@@ -2501,17 +2479,18 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
- std::string Input;
- std::string Content;
- std::string Condition;
- std::string Target;
- std::string NewLineStyle;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Input;
+ cm::optional<std::string> Content;
+ cm::optional<std::string> Condition;
+ cm::optional<std::string> Target;
+ cm::optional<std::string> NewLineStyle;
bool NoSourcePermissions = false;
bool UseSourcePermissions = false;
- std::vector<std::string> FilePermissions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> FilePermissions;
+ std::vector<cm::string_view> ParsedKeywords;
};
static auto const parser =
@@ -2524,18 +2503,15 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
.Bind("NO_SOURCE_PERMISSIONS"_s, &Arguments::NoSourcePermissions)
.Bind("USE_SOURCE_PERMISSIONS"_s, &Arguments::UseSourcePermissions)
.Bind("FILE_PERMISSIONS"_s, &Arguments::FilePermissions)
- .Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle);
+ .Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle)
+ .BindParsedKeywords(&Arguments::ParsedKeywords);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValues;
- std::vector<std::string> parsedKeywords;
Arguments const arguments =
- parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
- &keywordsMissingValues, &parsedKeywords);
+ parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments);
- if (!keywordsMissingValues.empty()) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!unparsedArguments.empty()) {
@@ -2543,56 +2519,41 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
return false;
}
- bool mandatoryOptionsSpecified = false;
- if (parsedKeywords.size() > 1) {
- const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s;
- const bool inputOrContentSpecified =
- parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s;
- if (outputOprionSpecified && inputOrContentSpecified) {
- mandatoryOptionsSpecified = true;
- }
+ if (!arguments.Output || arguments.ParsedKeywords[0] != "OUTPUT"_s) {
+ status.SetError("GENERATE requires OUTPUT as first option.");
+ return false;
}
- if (!mandatoryOptionsSpecified) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ std::string const& output = *arguments.Output;
+
+ if (!arguments.Input && !arguments.Content) {
+ status.SetError("GENERATE requires INPUT or CONTENT option.");
return false;
}
+ const bool inputIsContent = arguments.ParsedKeywords[1] == "CONTENT"_s;
+ if (!inputIsContent && arguments.ParsedKeywords[1] == "INPUT") {
+ status.SetError("Unknown argument to GENERATE subcommand.");
+ }
+ std::string const& input =
+ inputIsContent ? *arguments.Content : *arguments.Input;
- const bool conditionOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) !=
- parsedKeywords.end();
- if (conditionOptionSpecified && arguments.Condition.empty()) {
+ if (arguments.Condition && arguments.Condition->empty()) {
status.SetError("CONDITION of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& condition =
+ arguments.Condition ? *arguments.Condition : std::string();
- const bool targetOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) !=
- parsedKeywords.end();
- if (targetOptionSpecified && arguments.Target.empty()) {
+ if (arguments.Target && arguments.Target->empty()) {
status.SetError("TARGET of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& target =
+ arguments.Target ? *arguments.Target : std::string();
- const bool outputOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) !=
- parsedKeywords.end();
- if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
- return false;
- }
-
- const bool inputIsContent = parsedKeywords[1] != "INPUT"_s;
- if (inputIsContent && parsedKeywords[1] != "CONTENT") {
- status.SetError("Unknown argument to GENERATE subcommand.");
- }
-
- const bool newLineStyleSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(),
- "NEWLINE_STYLE"_s) != parsedKeywords.end();
cmNewLineStyle newLineStyle;
- if (newLineStyleSpecified) {
+ if (arguments.NewLineStyle) {
std::string errorMessage;
if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
status.SetError(cmStrCat("GENERATE ", errorMessage));
@@ -2600,11 +2561,6 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- std::string input = arguments.Input;
- if (inputIsContent) {
- input = arguments.Content;
- }
-
if (arguments.NoSourcePermissions && arguments.UseSourcePermissions) {
status.SetError("given both NO_SOURCE_PERMISSIONS and "
"USE_SOURCE_PERMISSIONS. Only one option allowed.");
@@ -2662,8 +2618,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- AddEvaluationFile(input, arguments.Target, arguments.Output,
- arguments.Condition, inputIsContent,
+ AddEvaluationFile(input, target, output, condition, inputIsContent,
newLineStyle.GetCharacters(), permissions, status);
return true;
}
@@ -2842,7 +2797,11 @@ bool HandleTimestampCommand(std::vector<std::string> const& args,
unsigned int argsIndex = 1;
- const std::string& filename = args[argsIndex++];
+ std::string filename = args[argsIndex++];
+ if (!cmsys::SystemTools::FileIsFullPath(filename)) {
+ filename = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+ filename);
+ }
const std::string& outputVariable = args[argsIndex++];
@@ -3003,11 +2962,23 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args,
// Check if the command requires a symbolic link.
if (arguments.Symbolic) {
- completed = static_cast<bool>(
- cmSystemTools::CreateSymlink(fileName, newFileName, &result));
+ cmsys::Status linked =
+ cmSystemTools::CreateSymlinkQuietly(fileName, newFileName);
+ if (linked) {
+ completed = true;
+ } else {
+ result = cmStrCat("failed to create symbolic link '", newFileName,
+ "': ", linked.GetString());
+ }
} else {
- completed = static_cast<bool>(
- cmSystemTools::CreateLink(fileName, newFileName, &result));
+ cmsys::Status linked =
+ cmSystemTools::CreateLinkQuietly(fileName, newFileName);
+ if (linked) {
+ completed = true;
+ } else {
+ result = cmStrCat("failed to create link '", newFileName,
+ "': ", linked.GetString());
+ }
}
// Check if copy-on-error is enabled in the arguments.
@@ -3066,24 +3037,25 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
"\n ]])");
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string ResolvedDependenciesVar;
std::string UnresolvedDependenciesVar;
std::string ConflictingDependenciesPrefix;
std::string RPathPrefix;
std::string BundleExecutable;
- std::vector<std::string> Executables;
- std::vector<std::string> Libraries;
- std::vector<std::string> Directories;
- std::vector<std::string> Modules;
- std::vector<std::string> PreIncludeRegexes;
- std::vector<std::string> PreExcludeRegexes;
- std::vector<std::string> PostIncludeRegexes;
- std::vector<std::string> PostExcludeRegexes;
- std::vector<std::string> PostIncludeFiles;
- std::vector<std::string> PostExcludeFiles;
- std::vector<std::string> PostExcludeFilesStrict;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Executables;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Libraries;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Modules;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>>
+ PostExcludeFilesStrict;
};
static auto const parser =
@@ -3108,10 +3080,8 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
.Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3119,26 +3089,9 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = {
- "DIRECTORIES",
- "EXECUTABLES",
- "LIBRARIES",
- "MODULES",
- "POST_EXCLUDE_FILES",
- "POST_EXCLUDE_FILES_STRICT",
- "POST_EXCLUDE_REGEXES",
- "POST_INCLUDE_FILES",
- "POST_INCLUDE_REGEXES",
- "PRE_EXCLUDE_REGEXES",
- "PRE_INCLUDE_REGEXES",
- };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
cmRuntimeDependencyArchive archive(
@@ -3238,13 +3191,14 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
bool HandleConfigureCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
- std::string Content;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Content;
bool EscapeQuotes = false;
bool AtOnly = false;
- std::string NewlineStyle;
+ // "NEWLINE_STYLE" requires one value, but we use a custom check below.
+ ArgumentParser::Maybe<std::string> NewlineStyle;
};
static auto const parser =
@@ -3256,11 +3210,8 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
.Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingArguments;
- std::vector<std::string> parsedKeywords;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingArguments, &parsedKeywords);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
@@ -3270,28 +3221,20 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
return false;
}
- std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" };
- for (auto const& e : mandatoryOptions) {
- const bool optionHasNoValue =
- std::find(keywordsMissingArguments.begin(),
- keywordsMissingArguments.end(),
- e) != keywordsMissingArguments.end();
- if (optionHasNoValue) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
+ cmSystemTools::SetFatalErrorOccurred();
+ return true;
}
- for (auto const& e : mandatoryOptions) {
- const bool optionGiven =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), e) !=
- parsedKeywords.end();
- if (!optionGiven) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ if (!parsedArgs.Output) {
+ status.SetError("CONFIGURE OUTPUT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+ if (!parsedArgs.Content) {
+ status.SetError("CONFIGURE CONTENT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
}
std::string errorMessage;
@@ -3303,7 +3246,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
// Check for generator expressions
std::string outputFile = cmSystemTools::CollapseFullPath(
- parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
+ *parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
std::string::size_type pos = outputFile.find_first_of("<>");
if (pos != std::string::npos) {
@@ -3352,7 +3295,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
fout.SetCopyIfDifferent(true);
// copy input to output and expand variables from input at the same time
- std::stringstream sin(parsedArgs.Content, std::ios::in);
+ std::stringstream sin(*parsedArgs.Content, std::ios::in);
std::string inLine;
std::string outLine;
bool hasNewLine = false;
@@ -3375,15 +3318,19 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string Output;
std::string Format;
std::string Compression;
std::string CompressionLevel;
- std::string MTime;
+ // "MTIME" should require one value, but it has long been accidentally
+ // accepted without one and treated as if an empty value were given.
+ // Fixing this would require a policy.
+ ArgumentParser::Maybe<std::string> MTime;
bool Verbose = false;
- std::vector<std::string> Paths;
+ // "PATHS" requires at least one value, but use a custom check below.
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Paths;
};
static auto const parser =
@@ -3397,10 +3344,8 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
.Bind("PATHS"_s, &Arguments::Paths);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3408,16 +3353,9 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = {
- "OUTPUT", "FORMAT", "COMPRESSION", "COMPRESSION_LEVEL", "MTIME", "PATHS"
- };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
const char* knownFormats[] = {
@@ -3506,13 +3444,13 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string Input;
bool Verbose = false;
bool ListOnly = false;
std::string Destination;
- std::vector<std::string> Patterns;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Patterns;
bool Touch = false;
};
@@ -3525,10 +3463,8 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
.Bind("TOUCH"_s, &Arguments::Touch);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3536,15 +3472,9 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = { "INPUT", "DESTINATION",
- "PATTERNS" };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
std::string inFile = parsedArgs.Input;
@@ -3599,10 +3529,15 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
return true;
}
-bool ValidateAndConvertPermissions(const std::vector<std::string>& permissions,
- mode_t& perms, cmExecutionStatus& status)
+bool ValidateAndConvertPermissions(
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> const&
+ permissions,
+ mode_t& perms, cmExecutionStatus& status)
{
- for (const auto& i : permissions) {
+ if (!permissions) {
+ return true;
+ }
+ for (const auto& i : *permissions) {
if (!cmFSPermissions::stringToModeT(i, perms)) {
status.SetError(i + " is an invalid permission specifier");
cmSystemTools::SetFatalErrorOccurred();
@@ -3634,11 +3569,14 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
globber.SetRecurse(recurse);
globber.SetRecurseListDirs(recurse);
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::vector<std::string> Permissions;
- std::vector<std::string> FilePermissions;
- std::vector<std::string> DirectoryPermissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ Permissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ FilePermissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ DirectoryPermissions;
};
static auto const parser =
@@ -3648,21 +3586,20 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
.Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions);
std::vector<std::string> pathEntries;
- std::vector<std::string> keywordsMissingValues;
- Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1),
- &pathEntries, &keywordsMissingValues);
+ Arguments parsedArgs =
+ parser.Parse(cmMakeRange(args).advance(1), &pathEntries);
// check validity of arguments
- if (parsedArgs.Permissions.empty() && parsedArgs.FilePermissions.empty() &&
- parsedArgs.DirectoryPermissions.empty()) // no permissions given
+ if (!parsedArgs.Permissions && !parsedArgs.FilePermissions &&
+ !parsedArgs.DirectoryPermissions) // no permissions given
{
status.SetError("No permissions given");
cmSystemTools::SetFatalErrorOccurred();
return false;
}
- if (!parsedArgs.Permissions.empty() && !parsedArgs.FilePermissions.empty() &&
- !parsedArgs.DirectoryPermissions.empty()) // all keywords are used
+ if (parsedArgs.Permissions && parsedArgs.FilePermissions &&
+ parsedArgs.DirectoryPermissions) // all keywords are used
{
status.SetError("Remove either PERMISSIONS or FILE_PERMISSIONS or "
"DIRECTORY_PERMISSIONS from the invocation");
@@ -3670,12 +3607,9 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
return false;
}
- if (!keywordsMissingValues.empty()) {
- for (const auto& i : keywordsMissingValues) {
- status.SetError(i + " is not given any arguments");
- cmSystemTools::SetFatalErrorOccurred();
- }
- return false;
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
+ cmSystemTools::SetFatalErrorOccurred();
+ return true;
}
// validate permissions
@@ -3719,7 +3653,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
if (cmSystemTools::FileExists(i, true)) {
bool success = true;
const mode_t& filePermissions =
- parsedArgs.FilePermissions.empty() ? perms : fperms;
+ parsedArgs.FilePermissions ? fperms : perms;
if (filePermissions) {
success = SetPermissions(i, filePermissions, status);
}
@@ -3731,7 +3665,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
else if (cmSystemTools::FileIsDirectory(i)) {
bool success = true;
const mode_t& directoryPermissions =
- parsedArgs.DirectoryPermissions.empty() ? perms : dperms;
+ parsedArgs.DirectoryPermissions ? dperms : perms;
if (directoryPermissions) {
success = SetPermissions(i, directoryPermissions, status);
}
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 16678074c..ef55abfd1 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -15,7 +15,11 @@
#include "cmValue.h"
#ifdef _WIN32
+# include <winerror.h>
+
# include "cmsys/FStream.hxx"
+#else
+# include <cerrno>
#endif
#include <cstring>
@@ -504,11 +508,12 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
cmSystemTools::RemoveFile(toFile);
cmSystemTools::MakeDirectory(toFilePath);
- if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
- std::ostringstream e;
- e << this->Name << " cannot create symlink \"" << toFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
- this->Status.SetError(e.str());
+ cmsys::Status status =
+ cmSystemTools::CreateSymlinkQuietly(symlinkTarget, toFile);
+ if (!status) {
+ std::string e = cmStrCat(this->Name, " cannot create symlink\n ",
+ toFile, "\nbecause: ", status.GetString());
+ this->Status.SetError(e);
return false;
}
}
@@ -557,12 +562,24 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
// Create the symlink.
- if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
- std::ostringstream e;
- e << this->Name << " cannot duplicate symlink \"" << fromFile
- << "\" at \"" << toFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
- this->Status.SetError(e.str());
+ cmsys::Status status =
+ cmSystemTools::CreateSymlinkQuietly(symlinkTarget, toFile);
+ if (!status) {
+#ifdef _WIN32
+ bool const errorFileExists = status.GetWindows() == ERROR_FILE_EXISTS;
+#else
+ bool const errorFileExists = status.GetPOSIX() == EEXIST;
+#endif
+ std::string reason;
+ if (errorFileExists && cmSystemTools::FileIsDirectory(toFile)) {
+ reason = "A directory already exists at that location";
+ } else {
+ reason = status.GetString();
+ }
+ std::string e =
+ cmStrCat(this->Name, " cannot duplicate symlink\n ", fromFile,
+ "\nat\n ", toFile, "\nbecause: ", reason);
+ this->Status.SetError(e);
return false;
}
}
@@ -630,7 +647,10 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
{
// Inform the user about this directory installation.
this->ReportCopy(destination, TypeDir,
- !cmSystemTools::FileIsDirectory(destination));
+ !( // Report "Up-to-date:" for existing directories,
+ // but not symlinks to them.
+ cmSystemTools::FileIsDirectory(destination) &&
+ !cmSystemTools::FileIsSymlink(destination)));
// check if default dir creation permissions were set
mode_t default_dir_mode_v = 0;
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 1da995a4b..b8d345f71 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -2,15 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindBase.h"
+#include <algorithm>
#include <cstddef>
#include <deque>
+#include <functional>
#include <map>
#include <utility>
#include <cm/optional>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmCMakePath.h"
+#include "cmExecutionStatus.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -24,8 +29,6 @@
#include "cmWindowsRegistry.h"
#include "cmake.h"
-class cmExecutionStatus;
-
cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status)
: cmFindCommon(status)
, FindCommandName(std::move(findCommandName))
@@ -138,6 +141,31 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j]));
return false;
}
+ } else if (args[j] == "VALIDATOR") {
+ if (++j == args.size()) {
+ this->SetError("missing required argument for \"VALIDATOR\"");
+ return false;
+ }
+ auto command = this->Makefile->GetState()->GetCommand(args[j]);
+ if (command == nullptr) {
+ this->SetError(cmStrCat(
+ "command specified for \"VALIDATOR\" is undefined: ", args[j], '.'));
+ return false;
+ }
+ // ensure a macro is not specified as validator
+ const auto& validatorName = args[j];
+ auto macros = cmExpandedList(this->Makefile->GetProperty("MACROS"));
+ if (std::find_if(macros.begin(), macros.end(),
+ [&validatorName](const std::string& item) {
+ return cmSystemTools::Strucmp(validatorName.c_str(),
+ item.c_str()) == 0;
+ }) != macros.end()) {
+ this->SetError(cmStrCat(
+ "command specified for \"VALIDATOR\" is not a function: ", args[j],
+ '.'));
+ return false;
+ }
+ this->ValidatorName = args[j];
} else if (this->CheckCommonArgument(args[j])) {
doing = DoingNone;
} else {
@@ -188,6 +216,36 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
return true;
}
+bool cmFindBase::Validate(const std::string& path) const
+{
+ if (this->ValidatorName.empty()) {
+ return true;
+ }
+
+ // The validator command will be executed in an isolated scope.
+ cmMakefile::ScopePushPop varScope(this->Makefile);
+ cmMakefile::PolicyPushPop polScope(this->Makefile);
+ static_cast<void>(varScope);
+ static_cast<void>(polScope);
+
+ auto resultName =
+ cmStrCat("CMAKE_"_s, cmSystemTools::UpperCase(this->FindCommandName),
+ "_VALIDATOR_STATUS"_s);
+
+ this->Makefile->AddDefinitionBool(resultName, true);
+
+ cmListFileFunction validator(
+ this->ValidatorName, 0, 0,
+ { cmListFileArgument(resultName, cmListFileArgument::Unquoted, 0),
+ cmListFileArgument(path, cmListFileArgument::Quoted, 0) });
+ cmExecutionStatus status(*this->Makefile);
+
+ if (this->Makefile->ExecuteCommand(validator, status)) {
+ return this->Makefile->GetDefinition(resultName).IsOn();
+ }
+ return false;
+}
+
void cmFindBase::ExpandPaths()
{
if (!this->NoDefaultPath) {
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index d197424db..75d9a6d25 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -31,6 +31,11 @@ public:
*/
virtual bool ParseArguments(std::vector<std::string> const& args);
+ /**
+ * To check validity of a found path using user's validator, if any
+ */
+ bool Validate(const std::string& path) const;
+
protected:
friend class cmFindBaseDebugState;
void ExpandPaths();
@@ -63,6 +68,8 @@ protected:
bool Required = false;
+ std::string ValidatorName;
+
private:
// Add pieces of the search.
void FillPackageRootPath();
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 1c4039b6f..6296a60ae 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -192,6 +192,7 @@ struct cmFindLibraryHelper
// Context information.
cmMakefile* Makefile;
+ cmFindBase const* FindBase;
cmGlobalGenerator* GG;
// List of valid prefixes and suffixes.
@@ -239,6 +240,11 @@ struct cmFindLibraryHelper
bool CheckDirectory(std::string const& path);
bool CheckDirectoryForName(std::string const& path, Name& name);
+ bool Validate(const std::string& path) const
+ {
+ return this->FindBase->Validate(path);
+ }
+
cmFindBaseDebugState DebugSearches;
void DebugLibraryFailed(std::string const& name, std::string const& path)
@@ -291,6 +297,7 @@ std::string const& get_suffixes(cmMakefile* mf)
cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
cmFindBase const* base)
: Makefile(mf)
+ , FindBase(base)
, DebugMode(base->DebugModeEnabled())
, DebugSearches(std::move(debugName), base)
{
@@ -416,10 +423,13 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
if (!exists) {
this->DebugLibraryFailed(name.Raw, path);
} else {
- this->DebugLibraryFound(name.Raw, path);
- this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
- cmSystemTools::ConvertToUnixSlashes(this->BestPath);
- return true;
+ auto testPath = cmSystemTools::CollapseFullPath(this->TestPath);
+ if (this->Validate(testPath)) {
+ this->DebugLibraryFound(name.Raw, path);
+ this->BestPath = testPath;
+ return true;
+ }
+ this->DebugLibraryFailed(name.Raw, path);
}
}
@@ -443,8 +453,11 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
this->TestPath = cmStrCat(path, origName);
// Make sure the path is readable and is not a directory.
if (cmSystemTools::FileExists(this->TestPath, true)) {
- this->DebugLibraryFound(name.Raw, dir);
+ if (!this->Validate(cmSystemTools::CollapseFullPath(this->TestPath))) {
+ continue;
+ }
+ this->DebugLibraryFound(name.Raw, dir);
// This is a matching file. Check if it is better than the
// best name found so far. Earlier prefixes are preferred,
// followed by earlier suffixes. For OpenBSD, shared library
@@ -541,7 +554,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
for (std::string const& n : this->Names) {
fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
- return cmSystemTools::CollapseFullPath(fwPath);
+ auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
+ if (this->Validate(finalPath)) {
+ return finalPath;
+ }
}
}
}
@@ -558,7 +574,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
for (std::string const& d : this->SearchPaths) {
fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
- return cmSystemTools::CollapseFullPath(fwPath);
+ auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
+ if (this->Validate(finalPath)) {
+ return finalPath;
+ }
}
}
}
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 8c6a0aa33..3f8378b02 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -5,7 +5,6 @@
#include <algorithm>
#include <cassert>
#include <cstdio>
-#include <cstring>
#include <deque>
#include <functional>
#include <iterator>
@@ -43,8 +42,405 @@
# include <StorageDefs.h>
#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include <windows.h>
+// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
+# if !defined(KEY_WOW64_32KEY)
+# define KEY_WOW64_32KEY 0x0200
+# endif
+# if !defined(KEY_WOW64_64KEY)
+# define KEY_WOW64_64KEY 0x0100
+# endif
+#endif
+
class cmExecutionStatus;
-class cmFileList;
+
+namespace {
+
+template <template <typename> class Op>
+struct StrverscmpOp
+{
+ bool operator()(const std::string& lhs, const std::string& rhs) const
+ {
+ return Op<int>()(cmSystemTools::strverscmp(lhs, rhs), 0);
+ }
+};
+
+std::size_t collectPathsForDebug(std::string& buffer,
+ cmSearchPath const& searchPath,
+ std::size_t const startIndex = 0)
+{
+ const auto& paths = searchPath.GetPaths();
+ if (paths.empty()) {
+ buffer += " none\n";
+ return 0;
+ }
+ for (auto i = startIndex; i < paths.size(); i++) {
+ buffer += " " + paths[i].Path + "\n";
+ }
+ return paths.size();
+}
+
+#if !(defined(_WIN32) && !defined(__CYGWIN__))
+class cmFindPackageCommandHoldFile
+{
+ const char* File;
+
+public:
+ cmFindPackageCommandHoldFile(const char* const f)
+ : File(f)
+ {
+ }
+ ~cmFindPackageCommandHoldFile()
+ {
+ if (this->File) {
+ cmSystemTools::RemoveFile(this->File);
+ }
+ }
+ cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete;
+ cmFindPackageCommandHoldFile& operator=(
+ const cmFindPackageCommandHoldFile&) = delete;
+ void Release() { this->File = nullptr; }
+};
+#endif
+
+bool isDirentryToIgnore(const char* const fname)
+{
+ assert(fname != nullptr);
+ assert(fname[0] != 0);
+ return fname[0] == '.' &&
+ (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0));
+}
+
+class cmAppendPathSegmentGenerator
+{
+public:
+ cmAppendPathSegmentGenerator(cm::string_view dirName)
+ : DirName{ dirName }
+ {
+ }
+
+ std::string GetNextCandidate(const std::string& parent)
+ {
+ if (this->NeedReset) {
+ return {};
+ }
+ this->NeedReset = true;
+ return cmStrCat(parent, '/', this->DirName);
+ }
+
+ void Reset() { this->NeedReset = false; }
+
+private:
+ const cm::string_view DirName;
+ bool NeedReset = false;
+};
+
+class cmEnumPathSegmentsGenerator
+{
+public:
+ cmEnumPathSegmentsGenerator(const std::vector<cm::string_view>& init)
+ : Names{ init }
+ , Current{ this->Names.get().cbegin() }
+ {
+ }
+
+ std::string GetNextCandidate(const std::string& parent)
+ {
+ if (this->Current != this->Names.get().cend()) {
+ return cmStrCat(parent, '/', *this->Current++);
+ }
+ return {};
+ }
+
+ void Reset() { this->Current = this->Names.get().cbegin(); }
+
+private:
+ std::reference_wrapper<const std::vector<cm::string_view>> Names;
+ std::vector<cm::string_view>::const_iterator Current;
+};
+
+class cmCaseInsensitiveDirectoryListGenerator
+{
+public:
+ cmCaseInsensitiveDirectoryListGenerator(cm::string_view name)
+ : DirectoryLister{}
+ , DirName{ name }
+ {
+ }
+
+ std::string GetNextCandidate(const std::string& parent)
+ {
+ if (!this->Loaded) {
+ this->CurrentIdx = 0ul;
+ this->Loaded = true;
+ if (!this->DirectoryLister.Load(parent)) {
+ return {};
+ }
+ }
+
+ while (this->CurrentIdx < this->DirectoryLister.GetNumberOfFiles()) {
+ const char* const fname =
+ this->DirectoryLister.GetFile(this->CurrentIdx++);
+ if (isDirentryToIgnore(fname)) {
+ continue;
+ }
+ if (cmsysString_strcasecmp(fname, this->DirName.data()) == 0) {
+ auto candidate = cmStrCat(parent, '/', fname);
+ if (cmSystemTools::FileIsDirectory(candidate)) {
+ return candidate;
+ }
+ }
+ }
+ return {};
+ }
+
+ void Reset() { this->Loaded = false; }
+
+private:
+ cmsys::Directory DirectoryLister;
+ const cm::string_view DirName;
+ unsigned long CurrentIdx = 0ul;
+ bool Loaded = false;
+};
+
+class cmDirectoryListGenerator
+{
+public:
+ cmDirectoryListGenerator(std::vector<std::string> const& names)
+ : Names{ names }
+ , Matches{}
+ , Current{ this->Matches.cbegin() }
+ {
+ }
+ virtual ~cmDirectoryListGenerator() = default;
+
+ std::string GetNextCandidate(const std::string& parent)
+ {
+ // Construct a list of matches if not yet
+ if (this->Matches.empty()) {
+ cmsys::Directory directoryLister;
+ // ALERT `Directory::Load()` keeps only names
+ // internally and LOST entry type from `dirent`.
+ // So, `Directory::FileIsDirectory` gonna use
+ // `SystemTools::FileIsDirectory()` and waste a syscall.
+ // TODO Need to enhance the `Directory` class.
+ directoryLister.Load(parent);
+
+ // ATTENTION Is it guaranteed that first two entries are
+ // `.` and `..`?
+ // TODO If so, just start with index 2 and drop the
+ // `isDirentryToIgnore(i)` condition to check.
+ for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) {
+ const char* const fname = directoryLister.GetFile(i);
+ if (isDirentryToIgnore(fname)) {
+ continue;
+ }
+
+ for (const auto& n : this->Names.get()) {
+ // NOTE Customization point for `cmMacProjectDirectoryListGenerator`
+ const auto name = this->TransformNameBeforeCmp(n);
+ // Skip entries that don't match and non-directories.
+ // ATTENTION BTW, original code also didn't check if it's a symlink
+ // to a directory!
+ const auto equal =
+ (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == 0);
+ if (equal && directoryLister.FileIsDirectory(i)) {
+ this->Matches.emplace_back(fname);
+ }
+ }
+ }
+ // NOTE Customization point for `cmProjectDirectoryListGenerator`
+ this->OnMatchesLoaded();
+
+ this->Current = this->Matches.cbegin();
+ }
+
+ if (this->Current != this->Matches.cend()) {
+ auto candidate = cmStrCat(parent, '/', *this->Current++);
+ return candidate;
+ }
+
+ return {};
+ }
+
+ void Reset()
+ {
+ this->Matches.clear();
+ this->Current = this->Matches.cbegin();
+ }
+
+protected:
+ virtual void OnMatchesLoaded() {}
+ virtual std::string TransformNameBeforeCmp(std::string same) { return same; }
+
+ std::reference_wrapper<const std::vector<std::string>> Names;
+ std::vector<std::string> Matches;
+ std::vector<std::string>::const_iterator Current;
+};
+
+class cmProjectDirectoryListGenerator : public cmDirectoryListGenerator
+{
+public:
+ cmProjectDirectoryListGenerator(std::vector<std::string> const& names,
+ cmFindPackageCommand::SortOrderType so,
+ cmFindPackageCommand::SortDirectionType sd)
+ : cmDirectoryListGenerator{ names }
+ , SortOrder{ so }
+ , SortDirection{ sd }
+ {
+ }
+
+protected:
+ void OnMatchesLoaded() override
+ {
+ // check if there is a specific sorting order to perform
+ if (this->SortOrder != cmFindPackageCommand::None) {
+ cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(),
+ this->SortOrder, this->SortDirection);
+ }
+ }
+
+private:
+ // sort parameters
+ const cmFindPackageCommand::SortOrderType SortOrder;
+ const cmFindPackageCommand::SortDirectionType SortDirection;
+};
+
+class cmMacProjectDirectoryListGenerator : public cmDirectoryListGenerator
+{
+public:
+ cmMacProjectDirectoryListGenerator(const std::vector<std::string>& names,
+ cm::string_view ext)
+ : cmDirectoryListGenerator{ names }
+ , Extension{ ext }
+ {
+ }
+
+protected:
+ std::string TransformNameBeforeCmp(std::string name) override
+ {
+ return cmStrCat(name, this->Extension);
+ }
+
+private:
+ const cm::string_view Extension;
+};
+
+class cmFileListGeneratorGlob
+{
+public:
+ cmFileListGeneratorGlob(cm::string_view pattern)
+ : Pattern(pattern)
+ , Files{}
+ , Current{}
+ {
+ }
+
+ std::string GetNextCandidate(const std::string& parent)
+ {
+ if (this->Files.empty()) {
+ // Glob the set of matching files.
+ std::string expr = cmStrCat(parent, this->Pattern);
+ cmsys::Glob g;
+ if (!g.FindFiles(expr)) {
+ return {};
+ }
+ this->Files = g.GetFiles();
+ this->Current = this->Files.cbegin();
+ }
+
+ // Skip non-directories
+ for (; this->Current != this->Files.cend() &&
+ !cmSystemTools::FileIsDirectory(*this->Current);
+ ++this->Current) {
+ }
+
+ return (this->Current != this->Files.cend()) ? *this->Current++
+ : std::string{};
+ }
+
+ void Reset()
+ {
+ this->Files.clear();
+ this->Current = this->Files.cbegin();
+ }
+
+private:
+ cm::string_view Pattern;
+ std::vector<std::string> Files;
+ std::vector<std::string>::const_iterator Current;
+};
+
+#if defined(__LCC__)
+# define CM_LCC_DIAG_SUPPRESS_1222
+# pragma diag_suppress 1222 // invalid error number (3288, but works anyway)
+# define CM_LCC_DIAG_SUPPRESS_3288
+# pragma diag_suppress 3288 // parameter was declared but never referenced
+#endif
+
+void ResetGenerator()
+{
+}
+
+template <typename Generator>
+void ResetGenerator(Generator&& generator)
+{
+ std::forward<Generator&&>(generator).Reset();
+}
+
+template <typename Generator, typename... Generators>
+void ResetGenerator(Generator&& generator, Generators&&... generators)
+{
+ ResetGenerator(std::forward<Generator&&>(generator));
+ ResetGenerator(std::forward<Generators&&>(generators)...);
+}
+
+template <typename CallbackFn>
+bool TryGeneratedPaths(CallbackFn&& filesCollector,
+ const std::string& fullPath)
+{
+ assert(!fullPath.empty() && fullPath.back() != '/');
+ return std::forward<CallbackFn&&>(filesCollector)(fullPath + '/');
+}
+
+template <typename CallbackFn, typename Generator, typename... Rest>
+bool TryGeneratedPaths(CallbackFn&& filesCollector,
+ const std::string& startPath, Generator&& gen,
+ Rest&&... tail)
+{
+ ResetGenerator(std::forward<Generator&&>(gen));
+ for (auto path = gen.GetNextCandidate(startPath); !path.empty();
+ path = gen.GetNextCandidate(startPath)) {
+ ResetGenerator(std::forward<Rest&&>(tail)...);
+ if (TryGeneratedPaths(std::forward<CallbackFn&&>(filesCollector), path,
+ std::forward<Rest&&>(tail)...)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifdef CM_LCC_DIAG_SUPPRESS_3288
+# undef CM_LCC_DIAG_SUPPRESS_3288
+# pragma diag_default 3288
+#endif
+
+#ifdef CM_LCC_DIAG_SUPPRESS_1222
+# undef CM_LCC_DIAG_SUPPRESS_1222
+# pragma diag_default 1222
+#endif
+
+// Parse the version number and store the results that were
+// successfully parsed.
+int parseVersion(const std::string& version, unsigned int& major,
+ unsigned int& minor, unsigned int& patch, unsigned int& tweak)
+{
+ return std::sscanf(version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch,
+ &tweak);
+}
+
+} // anonymous namespace
cmFindPackageCommand::PathLabel
cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT");
@@ -60,25 +456,10 @@ const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_INCLUDED(
const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_EXCLUDED(
"EXCLUDE");
-struct StrverscmpGreater
-{
- bool operator()(const std::string& lhs, const std::string& rhs) const
- {
- return cmSystemTools::strverscmp(lhs, rhs) > 0;
- }
-};
-
-struct StrverscmpLesser
-{
- bool operator()(const std::string& lhs, const std::string& rhs) const
- {
- return cmSystemTools::strverscmp(lhs, rhs) < 0;
- }
-};
-
void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
std::vector<std::string>::iterator end,
- SortOrderType order, SortDirectionType dir)
+ SortOrderType const order,
+ SortDirectionType const dir)
{
if (order == Name_order) {
if (dir == Dec) {
@@ -86,14 +467,13 @@ void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
} else {
std::sort(begin, end);
}
- } else if (order == Natural)
- // natural order uses letters and numbers (contiguous numbers digit are
- // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10
- {
+ } else if (order == Natural) {
+ // natural order uses letters and numbers (contiguous numbers digit are
+ // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10
if (dir == Dec) {
- std::sort(begin, end, StrverscmpGreater());
+ std::sort(begin, end, StrverscmpOp<std::greater>());
} else {
- std::sort(begin, end, StrverscmpLesser());
+ std::sort(begin, end, StrverscmpOp<std::less>());
}
}
// else do not sort
@@ -113,11 +493,10 @@ cmFindPackageCommand::cmFindPackageCommand(cmExecutionStatus& status)
void cmFindPackageCommand::AppendSearchPathGroups()
{
- std::vector<cmFindCommon::PathLabel>* labels;
-
// Update the All group with new paths. Note that package redirection must
// take precedence over everything else, so it has to be first in the array.
- labels = &this->PathGroupLabelMap[PathGroup::All];
+ std::vector<cmFindCommon::PathLabel>* const labels =
+ &this->PathGroupLabelMap[PathGroup::All];
labels->insert(labels->begin(), PathLabel::PackageRedirect);
labels->insert(
std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem),
@@ -147,15 +526,15 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
// Lookup required version of CMake.
- if (cmValue rv =
+ if (cmValue const rv =
this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
unsigned int v[3] = { 0, 0, 0 };
- sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]);
+ std::sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]);
this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]);
}
// Lookup target architecture, if any.
- if (cmValue arch =
+ if (cmValue const arch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
this->LibraryArchitecture = *arch;
}
@@ -184,7 +563,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// Check if User Package Registry should be disabled
// The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has
// priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
- if (cmValue def =
+ if (cmValue const def =
this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) {
this->NoUserRegistry = !cmIsOn(*def);
} else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
@@ -194,7 +573,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// Check if System Package Registry should be disabled
// The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has
// priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
- if (cmValue def = this->Makefile->GetDefinition(
+ if (cmValue const def = this->Makefile->GetDefinition(
"CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) {
this->NoSystemRegistry = !cmIsOn(*def);
} else if (this->Makefile->IsOn(
@@ -208,7 +587,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
// Check if Sorting should be enabled
- if (cmValue so =
+ if (cmValue const so =
this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {
if (*so == "NAME") {
@@ -219,7 +598,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->SortOrder = None;
}
}
- if (cmValue sd =
+ if (cmValue const sd =
this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) {
this->SortDirection = (*sd == "ASC") ? Asc : Dec;
}
@@ -265,9 +644,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
cmsys::RegularExpression versionRegex(
R"V(^([0-9]+(\.[0-9]+)*)(\.\.\.(<?)([0-9]+(\.[0-9]+)*))?$)V");
bool haveVersion = false;
- std::set<unsigned int> configArgs;
- std::set<unsigned int> moduleArgs;
- for (unsigned int i = 1; i < args.size(); ++i) {
+ std::vector<std::size_t> configArgs;
+ std::vector<std::size_t> moduleArgs;
+ for (std::size_t i = 1u; i < args.size(); ++i) {
if (args[i] == "QUIET") {
this->Quiet = true;
doing = DoingNone;
@@ -281,17 +660,17 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->GlobalScope = true;
doing = DoingNone;
} else if (args[i] == "MODULE") {
- moduleArgs.insert(i);
+ moduleArgs.push_back(i);
doing = DoingNone;
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
// NOLINTNEXTLINE(bugprone-branch-clone)
} else if (args[i] == "CONFIG") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
// NOLINTNEXTLINE(bugprone-branch-clone)
} else if (args[i] == "NO_MODULE") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
} else if (args[i] == "REQUIRED") {
this->Required = true;
@@ -301,36 +680,36 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
} else if (args[i] == "OPTIONAL_COMPONENTS") {
doing = DoingOptionalComponents;
} else if (args[i] == "NAMES") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNames;
} else if (args[i] == "PATHS") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingPaths;
} else if (args[i] == "HINTS") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingHints;
} else if (args[i] == "PATH_SUFFIXES") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingPathSuffixes;
} else if (args[i] == "CONFIGS") {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingConfigs;
} else if (args[i] == "NO_POLICY_SCOPE") {
this->PolicyScope = false;
doing = DoingNone;
} else if (args[i] == "NO_CMAKE_PACKAGE_REGISTRY") {
this->NoUserRegistry = true;
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
} else if (args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") {
this->NoSystemRegistry = true;
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
// NOLINTNEXTLINE(bugprone-branch-clone)
} else if (args[i] == "NO_CMAKE_BUILDS_PATH") {
// Ignore legacy option.
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
} else if (args[i] == "REGISTRY_VIEW") {
if (++i == args.size()) {
@@ -347,7 +726,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
return false;
}
} else if (this->CheckCommonArgument(args[i])) {
- configArgs.insert(i);
+ configArgs.push_back(i);
doing = DoingNone;
} else if ((doing == DoingComponents) ||
(doing == DoingOptionalComponents)) {
@@ -361,8 +740,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
requiredComponents.insert(args[i]);
}
- std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i];
- componentVarDefs.emplace_back(req_var, isRequired);
+ componentVarDefs.emplace_back(this->Name + "_FIND_REQUIRED_" + args[i],
+ isRequired);
// Append to the list of required components.
components += components_sep;
@@ -420,11 +799,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
if (!this->UseFindModules && !this->UseConfigFiles) {
std::ostringstream e;
e << "given options exclusive to Module mode:\n";
- for (unsigned int si : moduleArgs) {
+ for (auto si : moduleArgs) {
e << " " << args[si] << "\n";
}
e << "and options exclusive to Config mode:\n";
- for (unsigned int si : configArgs) {
+ for (auto si : configArgs) {
e << " " << args[si] << "\n";
}
e << "The options are incompatible.";
@@ -443,20 +822,20 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
if (this->VersionComplete.empty() || components.empty()) {
// Check whether we are recursing inside "Find<name>.cmake" within
// another find_package(<name>) call.
- std::string mod = cmStrCat(this->Name, "_FIND_MODULE");
+ std::string const mod = cmStrCat(this->Name, "_FIND_MODULE");
if (this->Makefile->IsOn(mod)) {
if (this->VersionComplete.empty()) {
// Get version information from the outer call if necessary.
// Requested version string.
- std::string ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE");
+ std::string const ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE");
this->VersionComplete = this->Makefile->GetSafeDefinition(ver);
// Whether an exact version is required.
- std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
+ std::string const exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
this->VersionExact = this->Makefile->IsOn(exact);
}
if (components.empty()) {
- std::string components_var = this->Name + "_FIND_COMPONENTS";
+ std::string const components_var = this->Name + "_FIND_COMPONENTS";
components = this->Makefile->GetSafeDefinition(components_var);
}
}
@@ -497,15 +876,6 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
return false;
}
- // Parse the version number and store the results that were
- // successfully parsed.
- auto parseVersion = [](const std::string& version, unsigned int& major,
- unsigned int& minor, unsigned int& patch,
- unsigned int& tweak) -> unsigned int {
- return sscanf(version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch,
- &tweak);
- };
-
if (!this->Version.empty()) {
this->VersionCount =
parseVersion(this->Version, this->VersionMajor, this->VersionMinor,
@@ -533,7 +903,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
}
- std::string disableFindPackageVar =
+ std::string const disableFindPackageVar =
cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
if (this->Makefile->IsOn(disableFindPackageVar)) {
if (this->Required) {
@@ -557,8 +927,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// A dependency provider (if set) gets first look before other methods.
// We do this before modifying the package root path stack because a
// provider might use methods that ignore that.
- cmState* state = this->Makefile->GetState();
- cmState::Command providerCommand = state->GetDependencyProviderCommand(
+ cmState* const state = this->Makefile->GetState();
+ cmState::Command const providerCommand = state->GetDependencyProviderCommand(
cmDependencyProvider::Method::FindPackage);
if (bypassProvider) {
if (this->DebugMode && providerCommand) {
@@ -725,11 +1095,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
"package configuration file provided by "
<< this->Name << " (" << this->Name << "Config.cmake or "
<< cmSystemTools::LowerCase(this->Name)
- << "-config.cmake). "
- "Otherwise make Find"
- << this->Name
- << ".cmake available in "
- "CMAKE_MODULE_PATH.";
+ << "-config.cmake). Otherwise make Find" << this->Name
+ << ".cmake available in CMAKE_MODULE_PATH.";
}
aw << "\n"
"(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this "
@@ -813,22 +1180,22 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode()
void cmFindPackageCommand::SetVersionVariables(
const std::function<void(const std::string&, cm::string_view)>&
addDefinition,
- const std::string& prefix, const std::string& version, unsigned int count,
- unsigned int major, unsigned int minor, unsigned int patch,
- unsigned int tweak)
+ const std::string& prefix, const std::string& version,
+ const unsigned int count, const unsigned int major, const unsigned int minor,
+ const unsigned int patch, const unsigned int tweak)
{
addDefinition(prefix, version);
char buf[64];
snprintf(buf, sizeof(buf), "%u", major);
addDefinition(prefix + "_MAJOR", buf);
- sprintf(buf, "%u", minor);
+ snprintf(buf, sizeof(buf), "%u", minor);
addDefinition(prefix + "_MINOR", buf);
- sprintf(buf, "%u", patch);
+ snprintf(buf, sizeof(buf), "%u", patch);
addDefinition(prefix + "_PATCH", buf);
- sprintf(buf, "%u", tweak);
+ snprintf(buf, sizeof(buf), "%u", tweak);
addDefinition(prefix + "_TWEAK", buf);
- sprintf(buf, "%u", count);
+ snprintf(buf, sizeof(buf), "%u", count);
addDefinition(prefix + "_COUNT", buf);
}
@@ -910,7 +1277,7 @@ void cmFindPackageCommand::SetModuleVariables(
}
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
- cm::string_view value)
+ const cm::string_view value)
{
if (cmValue old = this->Makefile->GetDefinition(var)) {
this->OriginalDefs[var].exists = true;
@@ -954,7 +1321,7 @@ bool cmFindPackageCommand::FindModule(bool& found)
if (!mfile.empty()) {
if (system) {
- auto it = this->DeprecatedFindModules.find(this->Name);
+ auto const it = this->DeprecatedFindModules.find(this->Name);
if (it != this->DeprecatedFindModules.end()) {
cmPolicies::PolicyStatus status =
this->Makefile->GetPolicyStatus(it->second);
@@ -978,13 +1345,13 @@ bool cmFindPackageCommand::FindModule(bool& found)
// Load the module we found, and set "<name>_FIND_MODULE" to true
// while inside it.
found = true;
- std::string var = cmStrCat(this->Name, "_FIND_MODULE");
+ std::string const var = cmStrCat(this->Name, "_FIND_MODULE");
this->Makefile->AddDefinition(var, "1");
bool result = this->ReadListFile(mfile, DoPolicyScope);
this->Makefile->RemoveDefinition(var);
if (this->DebugMode) {
- std::string foundVar = cmStrCat(this->Name, "_FOUND");
+ std::string const foundVar = cmStrCat(this->Name, "_FOUND");
if (this->Makefile->IsDefinitionSet(foundVar) &&
!this->Makefile->IsOn(foundVar)) {
@@ -999,7 +1366,7 @@ bool cmFindPackageCommand::FindModule(bool& found)
}
bool cmFindPackageCommand::HandlePackageMode(
- HandlePackageModeType handlePackageModeType)
+ const HandlePackageModeType handlePackageModeType)
{
this->ConsideredConfigs.clear();
@@ -1042,8 +1409,9 @@ bool cmFindPackageCommand::HandlePackageMode(
}
}
- std::string foundVar = cmStrCat(this->Name, "_FOUND");
- std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
+ std::string const foundVar = cmStrCat(this->Name, "_FOUND");
+ std::string const notFoundMessageVar =
+ cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
std::string notFoundMessage;
// If the directory for the config file was found, try to read the file.
@@ -1123,8 +1491,9 @@ bool cmFindPackageCommand::HandlePackageMode(
<< (this->VersionExact ? "exactly matches" : "is compatible with")
<< " requested version "
<< (this->VersionRange.empty() ? "" : "range ") << "\""
- << this->VersionComplete << "\".\n"
- << "The following configuration files were considered but not "
+ << this->VersionComplete
+ << "\".\n"
+ "The following configuration files were considered but not "
"accepted:\n";
for (ConfigFileInfo const& info :
@@ -1172,8 +1541,9 @@ bool cmFindPackageCommand::HandlePackageMode(
"package or SDK, be sure it has been installed.";
} else // if(!this->UseFindModules && !this->UseConfigFiles)
{
- e << "No \"Find" << this->Name << ".cmake\" found in "
- << "CMAKE_MODULE_PATH.";
+ e << "No \"Find" << this->Name
+ << ".cmake\" found in "
+ "CMAKE_MODULE_PATH.";
aw
<< "Find" << this->Name
@@ -1217,16 +1587,16 @@ bool cmFindPackageCommand::HandlePackageMode(
this->Makefile->AddDefinition(foundVar, found ? "1" : "0");
// Set a variable naming the configuration file that was found.
- std::string fileVar = cmStrCat(this->Name, "_CONFIG");
+ std::string const fileVar = cmStrCat(this->Name, "_CONFIG");
if (found) {
this->Makefile->AddDefinition(fileVar, this->FileFound);
} else {
this->Makefile->RemoveDefinition(fileVar);
}
- std::string consideredConfigsVar =
+ std::string const consideredConfigsVar =
cmStrCat(this->Name, "_CONSIDERED_CONFIGS");
- std::string consideredVersionsVar =
+ std::string const consideredVersionsVar =
cmStrCat(this->Name, "_CONSIDERED_VERSIONS");
std::string consideredConfigFiles;
@@ -1312,7 +1682,7 @@ bool cmFindPackageCommand::FindConfig()
void cmFindPackageCommand::SetConfigDirCacheVariable(const std::string& value)
{
- std::string help =
+ std::string const help =
cmStrCat("The directory containing a CMake configuration file for ",
this->Name, '.');
this->Makefile->AddCacheDefinition(this->Variable, value, help.c_str(),
@@ -1351,7 +1721,7 @@ bool cmFindPackageCommand::FindAppBundleConfig()
}
bool cmFindPackageCommand::ReadListFile(const std::string& f,
- PolicyScopeRule psr)
+ const PolicyScopeRule psr)
{
const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope;
@@ -1362,12 +1732,12 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f,
if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
return true;
}
- std::string e = cmStrCat("Error reading CMake code from \"", f, "\".");
+ std::string const e = cmStrCat("Error reading CMake code from \"", f, "\".");
this->SetError(e);
return false;
}
-void cmFindPackageCommand::AppendToFoundProperty(bool found)
+void cmFindPackageCommand::AppendToFoundProperty(const bool found)
{
std::vector<std::string> foundContents;
cmValue foundProp =
@@ -1410,27 +1780,28 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
void cmFindPackageCommand::AppendSuccessInformation()
{
{
- std::string transitivePropName =
+ std::string const transitivePropName =
cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY");
this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
}
- std::string found = cmStrCat(this->Name, "_FOUND");
- std::string upperFound = cmSystemTools::UpperCase(found);
+ std::string const found = cmStrCat(this->Name, "_FOUND");
+ std::string const upperFound = cmSystemTools::UpperCase(found);
- bool upperResult = this->Makefile->IsOn(upperFound);
- bool result = this->Makefile->IsOn(found);
- bool packageFound = (result || upperResult);
+ bool const upperResult = this->Makefile->IsOn(upperFound);
+ bool const result = this->Makefile->IsOn(found);
+ bool const packageFound = (result || upperResult);
this->AppendToFoundProperty(packageFound);
// Record whether the find was quiet or not, so this can be used
// e.g. in FeatureSummary.cmake
- std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET");
+ std::string const quietInfoPropName =
+ cmStrCat("_CMAKE_", this->Name, "_QUIET");
this->Makefile->GetState()->SetGlobalProperty(
quietInfoPropName, this->Quiet ? "TRUE" : "FALSE");
// set a global property to record the required version of this package
- std::string versionInfoPropName =
+ std::string const versionInfoPropName =
cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION");
std::string versionInfo;
if (!this->VersionRange.empty()) {
@@ -1442,28 +1813,13 @@ void cmFindPackageCommand::AppendSuccessInformation()
this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
versionInfo.c_str());
if (this->Required) {
- std::string requiredInfoPropName =
+ std::string const requiredInfoPropName =
cmStrCat("_CMAKE_", this->Name, "_TYPE");
this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
"REQUIRED");
}
}
-inline std::size_t collectPathsForDebug(std::string& buffer,
- cmSearchPath const& searchPath,
- std::size_t startIndex = 0)
-{
- const auto& paths = searchPath.GetPaths();
- if (paths.empty()) {
- buffer += " none\n";
- return 0;
- }
- for (std::size_t i = startIndex; i < paths.size(); i++) {
- buffer += " " + paths[i].Path + "\n";
- }
- return paths.size();
-}
-
void cmFindPackageCommand::ComputePrefixes()
{
this->FillPrefixesPackageRedirect();
@@ -1674,14 +2030,6 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry()
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <windows.h>
-// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
-# if !defined(KEY_WOW64_32KEY)
-# define KEY_WOW64_32KEY 0x0200
-# endif
-# if !defined(KEY_WOW64_64KEY)
-# define KEY_WOW64_64KEY 0x0100
-# endif
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
// HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
@@ -1704,7 +2052,8 @@ void cmFindPackageCommand::LoadPackageRegistryWinSystem()
}
}
-void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
+void cmFindPackageCommand::LoadPackageRegistryWin(const bool user,
+ const unsigned int view,
cmSearchPath& outPaths)
{
std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
@@ -1756,28 +2105,8 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
RegCloseKey(hKey);
}
}
-#else
-class cmFindPackageCommandHoldFile
-{
- const char* File;
-
-public:
- cmFindPackageCommandHoldFile(const char* f)
- : File(f)
- {
- }
- ~cmFindPackageCommandHoldFile()
- {
- if (this->File) {
- cmSystemTools::RemoveFile(this->File);
- }
- }
- cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete;
- cmFindPackageCommandHoldFile& operator=(
- const cmFindPackageCommandHoldFile&) = delete;
- void Release() { this->File = nullptr; }
-};
+#else
void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
cmSearchPath& outPaths)
{
@@ -1877,7 +2206,7 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
std::vector<std::string> expanded = cmExpandedList(*prefix_paths);
long count = 0;
for (const auto& path : expanded) {
- bool to_add =
+ bool const to_add =
!(path == install_path_to_remove && ++count == install_prefix_count);
if (to_add) {
paths.AddPath(path);
@@ -1941,7 +2270,7 @@ bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
std::string d = dir;
if (!s.empty()) {
d += s;
- d += "/";
+ d += '/';
}
if (this->CheckDirectory(d)) {
return true;
@@ -1955,7 +2284,7 @@ bool cmFindPackageCommand::CheckDirectory(std::string const& dir)
assert(!dir.empty() && dir.back() == '/');
// Look for the file in this directory.
- std::string d = dir.substr(0, dir.size() - 1);
+ std::string const d = dir.substr(0, dir.size() - 1);
if (this->FindConfigFile(d, this->FileFound)) {
// Remove duplicate slashes.
cmSystemTools::ConvertToUnixSlashes(this->FileFound);
@@ -2028,8 +2357,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
std::string& result_version)
{
// The version file will be loaded in an isolated scope.
- cmMakefile::ScopePushPop varScope(this->Makefile);
- cmMakefile::PolicyPushPop polScope(this->Makefile);
+ cmMakefile::ScopePushPop const varScope(this->Makefile);
+ cmMakefile::PolicyPushPop const polScope(this->Makefile);
static_cast<void>(varScope);
static_cast<void>(polScope);
@@ -2076,7 +2405,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
if (this->ReadListFile(version_file, NoPolicyScope)) {
// Check the output variables.
bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT");
- bool unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
+ bool const unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
if (!okay && !this->VersionExact) {
okay = this->Makefile->IsOn("PACKAGE_VERSION_COMPATIBLE");
}
@@ -2096,8 +2425,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
unsigned int parsed_patch;
unsigned int parsed_tweak;
this->VersionFoundCount =
- sscanf(this->VersionFound.c_str(), "%u.%u.%u.%u", &parsed_major,
- &parsed_minor, &parsed_patch, &parsed_tweak);
+ parseVersion(this->VersionFound, parsed_major, parsed_minor,
+ parsed_patch, parsed_tweak);
switch (this->VersionFoundCount) {
case 4:
this->VersionFoundTweak = parsed_tweak;
@@ -2129,7 +2458,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
void cmFindPackageCommand::StoreVersionFound()
{
// Store the whole version string.
- std::string ver = cmStrCat(this->Name, "_VERSION");
+ std::string const ver = cmStrCat(this->Name, "_VERSION");
auto addDefinition = [this](const std::string& variable,
cm::string_view value) {
this->Makefile->AddDefinition(variable, value);
@@ -2145,357 +2474,6 @@ void cmFindPackageCommand::StoreVersionFound()
}
}
-class cmFileListGeneratorBase
-{
-public:
- virtual ~cmFileListGeneratorBase() = default;
-
-protected:
- bool Consider(std::string const& fullPath, cmFileList& listing);
-
-private:
- bool Search(cmFileList&);
- virtual bool Search(std::string const& parent, cmFileList&) = 0;
- virtual std::unique_ptr<cmFileListGeneratorBase> Clone() const = 0;
- friend class cmFileList;
- cmFileListGeneratorBase* SetNext(cmFileListGeneratorBase const& next);
- std::unique_ptr<cmFileListGeneratorBase> Next;
-};
-
-class cmFileList
-{
-public:
- virtual ~cmFileList() = default;
- cmFileList& operator/(cmFileListGeneratorBase const& rhs)
- {
- if (this->Last) {
- this->Last = this->Last->SetNext(rhs);
- } else {
- this->First = rhs.Clone();
- this->Last = this->First.get();
- }
- return *this;
- }
- bool Search()
- {
- if (this->First) {
- return this->First->Search(*this);
- }
- return false;
- }
-
-private:
- virtual bool Visit(std::string const& fullPath) = 0;
- friend class cmFileListGeneratorBase;
- std::unique_ptr<cmFileListGeneratorBase> First;
- cmFileListGeneratorBase* Last = nullptr;
-};
-
-class cmFindPackageFileList : public cmFileList
-{
-public:
- cmFindPackageFileList(cmFindPackageCommand* fpc, bool use_suffixes = true)
- : FPC(fpc)
- , UseSuffixes(use_suffixes)
- {
- }
-
-private:
- bool Visit(std::string const& fullPath) override
- {
- if (this->UseSuffixes) {
- return this->FPC->SearchDirectory(fullPath);
- }
- return this->FPC->CheckDirectory(fullPath);
- }
- cmFindPackageCommand* FPC;
- bool UseSuffixes;
-};
-
-bool cmFileListGeneratorBase::Search(cmFileList& listing)
-{
- return this->Search("", listing);
-}
-
-cmFileListGeneratorBase* cmFileListGeneratorBase::SetNext(
- cmFileListGeneratorBase const& next)
-{
- this->Next = next.Clone();
- return this->Next.get();
-}
-
-bool cmFileListGeneratorBase::Consider(std::string const& fullPath,
- cmFileList& listing)
-{
- if (!fullPath.empty() && !cmSystemTools::FileIsDirectory(fullPath)) {
- return false;
- }
- if (this->Next) {
- return this->Next->Search(fullPath + "/", listing);
- }
- return listing.Visit(fullPath + "/");
-}
-
-class cmFileListGeneratorFixed : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorFixed(std::string str)
- : String(std::move(str))
- {
- }
- cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r)
- : String(r.String)
- {
- }
-
-private:
- std::string String;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- std::string fullPath = parent + this->String;
- return this->Consider(fullPath, lister);
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- std::unique_ptr<cmFileListGeneratorBase> g(
- new cmFileListGeneratorFixed(*this));
- return g;
- }
-};
-
-class cmFileListGeneratorEnumerate : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorEnumerate(std::vector<std::string> const& v)
- : Vector(v)
- {
- }
- cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r)
- : Vector(r.Vector)
- {
- }
-
-private:
- std::vector<std::string> const& Vector;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- for (std::string const& i : this->Vector) {
- if (this->Consider(parent + i, lister)) {
- return true;
- }
- }
- return false;
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- std::unique_ptr<cmFileListGeneratorBase> g(
- new cmFileListGeneratorEnumerate(*this));
- return g;
- }
-};
-
-class cmFileListGeneratorProject : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorProject(std::vector<std::string> const& names,
- cmFindPackageCommand::SortOrderType so,
- cmFindPackageCommand::SortDirectionType sd)
- : Names(names)
- {
- this->SetSort(so, sd);
- }
- cmFileListGeneratorProject(cmFileListGeneratorProject const& r)
- : Names(r.Names)
- {
- this->SetSort(r.SortOrder, r.SortDirection);
- }
-
- void SetSort(cmFindPackageCommand::SortOrderType o,
- cmFindPackageCommand::SortDirectionType d)
- {
- this->SortOrder = o;
- this->SortDirection = d;
- }
-
-protected:
- // sort parameters
- cmFindPackageCommand::SortOrderType SortOrder;
- cmFindPackageCommand::SortDirectionType SortDirection;
-
-private:
- std::vector<std::string> const& Names;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- // Construct a list of matches.
- std::vector<std::string> matches;
- cmsys::Directory d;
- d.Load(parent);
- for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
- const char* fname = d.GetFile(i);
- if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
- continue;
- }
- for (std::string const& n : this->Names) {
- if (cmsysString_strncasecmp(fname, n.c_str(), n.length()) == 0) {
- matches.emplace_back(fname);
- }
- }
- }
-
- // before testing the matches check if there is a specific sorting order to
- // perform
- if (this->SortOrder != cmFindPackageCommand::None) {
- cmFindPackageCommand::Sort(matches.begin(), matches.end(),
- this->SortOrder, this->SortDirection);
- }
-
- for (std::string const& i : matches) {
- if (this->Consider(parent + i, lister)) {
- return true;
- }
- }
- return false;
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- std::unique_ptr<cmFileListGeneratorBase> g(
- new cmFileListGeneratorProject(*this));
- return g;
- }
-};
-
-class cmFileListGeneratorMacProject : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorMacProject(std::vector<std::string> const& names,
- const char* ext)
- : Names(names)
- , Extension(ext)
- {
- }
- cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r)
- : Names(r.Names)
- , Extension(r.Extension)
- {
- }
-
-private:
- std::vector<std::string> const& Names;
- std::string Extension;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- // Construct a list of matches.
- std::vector<std::string> matches;
- cmsys::Directory d;
- d.Load(parent);
- for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
- const char* fname = d.GetFile(i);
- if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
- continue;
- }
- for (std::string name : this->Names) {
- name += this->Extension;
- if (cmsysString_strcasecmp(fname, name.c_str()) == 0) {
- matches.emplace_back(fname);
- }
- }
- }
-
- for (std::string const& i : matches) {
- if (this->Consider(parent + i, lister)) {
- return true;
- }
- }
- return false;
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- std::unique_ptr<cmFileListGeneratorBase> g(
- new cmFileListGeneratorMacProject(*this));
- return g;
- }
-};
-
-class cmFileListGeneratorCaseInsensitive : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorCaseInsensitive(std::string str)
- : String(std::move(str))
- {
- }
- cmFileListGeneratorCaseInsensitive(
- cmFileListGeneratorCaseInsensitive const& r)
- : String(r.String)
- {
- }
-
-private:
- std::string String;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- // Look for matching files.
- std::vector<std::string> matches;
- cmsys::Directory d;
- d.Load(parent);
- for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
- const char* fname = d.GetFile(i);
- if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
- continue;
- }
- if (cmsysString_strcasecmp(fname, this->String.c_str()) == 0) {
- if (this->Consider(parent + fname, lister)) {
- return true;
- }
- }
- }
- return false;
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- std::unique_ptr<cmFileListGeneratorBase> g(
- new cmFileListGeneratorCaseInsensitive(*this));
- return g;
- }
-};
-
-class cmFileListGeneratorGlob : public cmFileListGeneratorBase
-{
-public:
- cmFileListGeneratorGlob(std::string str)
- : Pattern(std::move(str))
- {
- }
- cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r)
- : Pattern(r.Pattern)
- {
- }
-
-private:
- std::string Pattern;
- bool Search(std::string const& parent, cmFileList& lister) override
- {
- // Glob the set of matching files.
- std::string expr = cmStrCat(parent, this->Pattern);
- cmsys::Glob g;
- if (!g.FindFiles(expr)) {
- return false;
- }
- std::vector<std::string> const& files = g.GetFiles();
-
- // Look for directories among the matches.
- for (std::string const& f : files) {
- if (this->Consider(f, lister)) {
- return true;
- }
- }
- return false;
- }
- std::unique_ptr<cmFileListGeneratorBase> Clone() const override
- {
- return cm::make_unique<cmFileListGeneratorGlob>(*this);
- }
-};
-
bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
{
assert(!prefix_in.empty() && prefix_in.back() == '/');
@@ -2515,148 +2493,101 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
return false;
}
- // PREFIX/ (useful on windows or in build trees)
+ // PREFIX/ (useful on windows or in build trees)
if (this->SearchDirectory(prefix_in)) {
return true;
}
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
+ std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1);
- // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
+ auto searchFn = [this](const std::string& fullPath) -> bool {
+ return this->SearchDirectory(fullPath);
+ };
+
+ auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
+ auto firstPkgDirGen =
+ cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
+ this->SortDirection };
+
+ // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
+ if (TryGeneratedPaths(searchFn, prefix, iCMakeGen)) {
+ return true;
}
- // PREFIX/(Foo|foo|FOO).*/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection);
- if (lister.Search()) {
- return true;
- }
+ // PREFIX/(Foo|foo|FOO).*/
+ if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen)) {
+ return true;
}
- // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
+ // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/
+ if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen)) {
+ return true;
+ }
+
+ auto secondPkgDirGen =
+ cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
+ this->SortDirection };
+
+ // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/
+ if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen,
+ secondPkgDirGen)) {
+ return true;
}
// Construct list of common install locations (lib and share).
- std::vector<std::string> common;
+ std::vector<cm::string_view> common;
+ std::string libArch;
if (!this->LibraryArchitecture.empty()) {
- common.push_back("lib/" + this->LibraryArchitecture);
+ libArch = "lib/" + this->LibraryArchitecture;
+ common.emplace_back(libArch);
}
if (this->UseLib32Paths) {
- common.emplace_back("lib32");
+ common.emplace_back("lib32"_s);
}
if (this->UseLib64Paths) {
- common.emplace_back("lib64");
+ common.emplace_back("lib64"_s);
}
if (this->UseLibx32Paths) {
- common.emplace_back("libx32");
+ common.emplace_back("libx32"_s);
}
- common.emplace_back("lib");
- common.emplace_back("share");
+ common.emplace_back("lib"_s);
+ common.emplace_back("share"_s);
- // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorFixed("cmake") /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection);
- if (lister.Search()) {
- return true;
- }
+ auto cmnGen = cmEnumPathSegmentsGenerator{ common };
+ auto cmakeGen = cmAppendPathSegmentGenerator{ "cmake"_s };
+
+ // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
+ if (TryGeneratedPaths(searchFn, prefix, cmnGen, cmakeGen, firstPkgDirGen)) {
+ return true;
}
- // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection);
- if (lister.Search()) {
- return true;
- }
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
+ if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen)) {
+ return true;
}
- // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen, iCMakeGen)) {
+ return true;
}
// PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorFixed("cmake") /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection);
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen, cmakeGen,
+ secondPkgDirGen)) {
+ return true;
}
// PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection);
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen,
+ secondPkgDirGen)) {
+ return true;
}
// PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorEnumerate(common) /
- cmFileListGeneratorProject(this->Names, this->SortOrder,
- this->SortDirection) /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
- }
-
- return false;
+ return TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen,
+ secondPkgDirGen, iCMakeGen);
}
bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
@@ -2665,56 +2596,36 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
+ std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1);
+
+ auto searchFn = [this](const std::string& fullPath) -> bool {
+ return this->SearchDirectory(fullPath);
+ };
+
+ auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
+ auto fwGen =
+ cmMacProjectDirectoryListGenerator{ this->Names, ".framework"_s };
+ auto rGen = cmAppendPathSegmentGenerator{ "Resources"_s };
+ auto vGen = cmAppendPathSegmentGenerator{ "Versions"_s };
+ auto grGen = cmFileListGeneratorGlob{ "/*/Resources"_s };
// <prefix>/Foo.framework/Resources/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".framework") /
- cmFileListGeneratorFixed("Resources");
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, fwGen, rGen)) {
+ return true;
}
+
// <prefix>/Foo.framework/Resources/CMake/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".framework") /
- cmFileListGeneratorFixed("Resources") /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, fwGen, rGen, iCMakeGen)) {
+ return true;
}
// <prefix>/Foo.framework/Versions/*/Resources/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".framework") /
- cmFileListGeneratorFixed("Versions") /
- cmFileListGeneratorGlob("*/Resources");
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, fwGen, vGen, grGen)) {
+ return true;
}
// <prefix>/Foo.framework/Versions/*/Resources/CMake/
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".framework") /
- cmFileListGeneratorFixed("Versions") /
- cmFileListGeneratorGlob("*/Resources") /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
- }
-
- return false;
+ return TryGeneratedPaths(searchFn, prefix, fwGen, vGen, grGen, iCMakeGen);
}
bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
@@ -2723,32 +2634,24 @@ bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
+ std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1);
+
+ auto searchFn = [this](const std::string& fullPath) -> bool {
+ return this->SearchDirectory(fullPath);
+ };
+
+ auto appGen = cmMacProjectDirectoryListGenerator{ this->Names, ".app"_s };
+ auto crGen = cmAppendPathSegmentGenerator{ "Contents/Resources"_s };
// <prefix>/Foo.app/Contents/Resources
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".app") /
- cmFileListGeneratorFixed("Contents/Resources");
- if (lister.Search()) {
- return true;
- }
+ if (TryGeneratedPaths(searchFn, prefix, appGen, crGen)) {
+ return true;
}
// <prefix>/Foo.app/Contents/Resources/CMake
- {
- cmFindPackageFileList lister(this);
- lister / cmFileListGeneratorFixed(prefix) /
- cmFileListGeneratorMacProject(this->Names, ".app") /
- cmFileListGeneratorFixed("Contents/Resources") /
- cmFileListGeneratorCaseInsensitive("cmake");
- if (lister.Search()) {
- return true;
- }
- }
-
- return false;
+ return TryGeneratedPaths(
+ searchFn, prefix, appGen, crGen,
+ cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s });
}
// TODO: Debug cmsys::Glob double slash problem.
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 80fd8f8ca..28e00a109 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -153,8 +153,6 @@ private:
bool SearchFrameworkPrefix(std::string const& prefix_in);
bool SearchAppBundlePrefix(std::string const& prefix_in);
- friend class cmFindPackageFileList;
-
struct OriginalDef
{
bool exists;
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 27074ff31..74a69d80a 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -88,7 +88,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(
if (!frameWorkName.empty()) {
std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
- if (cmSystemTools::FileExists(intPath)) {
+ if (cmSystemTools::FileExists(intPath) &&
+ this->Validate(this->IncludeFileInPath ? intPath : fpath)) {
debug.FoundAt(intPath);
if (this->IncludeFileInPath) {
return intPath;
@@ -124,7 +125,8 @@ std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
for (std::string const& n : this->Names) {
for (std::string const& sp : this->SearchPaths) {
tryPath = cmStrCat(sp, n);
- if (cmSystemTools::FileExists(tryPath)) {
+ if (cmSystemTools::FileExists(tryPath) &&
+ this->Validate(this->IncludeFileInPath ? tryPath : sp)) {
debug.FoundAt(tryPath);
if (this->IncludeFileInPath) {
return tryPath;
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index a64e0e4dd..8a2a69e42 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -27,6 +27,7 @@ struct cmFindProgramHelper
cmFindBase const* base)
: DebugSearches(std::move(debugName), base)
, Makefile(makefile)
+ , FindBase(base)
, PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
{
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
@@ -56,6 +57,7 @@ struct cmFindProgramHelper
// Debug state
cmFindBaseDebugState DebugSearches;
cmMakefile* Makefile;
+ cmFindBase const* FindBase;
cmPolicies::PolicyStatus PolicyCMP0109;
@@ -94,7 +96,7 @@ struct cmFindProgramHelper
this->TestNameExt = cmStrCat(name, ext);
this->TestPath = cmSystemTools::CollapseFullPath(
this->TestNameExt, path);
- bool exists = this->FileIsExecutable(this->TestPath);
+ bool exists = this->FileIsValid(this->TestPath);
exists ? this->DebugSearches.FoundAt(this->TestPath)
: this->DebugSearches.FailedAt(this->TestPath);
if (exists) {
@@ -104,12 +106,12 @@ struct cmFindProgramHelper
return false;
});
}
- bool FileIsExecutable(std::string const& file) const
+ bool FileIsValid(std::string const& file) const
{
-#ifdef _WIN32
if (!this->FileIsExecutableCMP0109(file)) {
return false;
}
+#ifdef _WIN32
// Pretend the Windows "python" app installer alias does not exist.
if (cmSystemTools::LowerCase(file).find("/windowsapps/python") !=
std::string::npos) {
@@ -119,10 +121,8 @@ struct cmFindProgramHelper
return false;
}
}
- return true;
-#else
- return this->FileIsExecutableCMP0109(file);
#endif
+ return this->FindBase->Validate(file);
}
bool FileIsExecutableCMP0109(std::string const& file) const
{
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index b9400c95f..3465c230f 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -260,7 +260,7 @@ auto cmForEachFunctionBlocker::invoke(
cmExecutionStatus status(mf);
mf.ExecuteCommand(func, status);
if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
+ inStatus.SetReturnInvoked(status.GetReturnVariables());
result.Break = true;
break;
}
diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx
index 40e692d0e..523482a70 100644
--- a/Source/cmFunctionBlocker.cxx
+++ b/Source/cmFunctionBlocker.cxx
@@ -24,10 +24,11 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
auto self = mf.RemoveFunctionBlocker();
assert(self.get() == this);
- if (!this->ArgumentsMatch(lff, mf)) {
- cmListFileContext const& lfc = this->GetStartingContext();
- cmListFileContext closingContext =
- cmListFileContext::FromListFileFunction(lff, lfc.FilePath);
+ cmListFileContext const& lfc = this->GetStartingContext();
+ cmListFileContext closingContext =
+ cmListFileContext::FromListFileFunction(lff, lfc.FilePath);
+ if (this->EndCommandSupportsArguments() &&
+ !this->ArgumentsMatch(lff, mf)) {
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
@@ -37,6 +38,15 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
<< "with mis-matching arguments.";
/* clang-format on */
mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ } else if (!this->EndCommandSupportsArguments() &&
+ !lff.Arguments().empty()) {
+ std::ostringstream e;
+ /* clang-format off */
+ e << "A logical block closing on the line\n"
+ " " << closingContext << "\n"
+ "has unexpected arguments.";
+ /* clang-format on */
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
return this->Replay(std::move(this->Functions), status);
diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h
index 38abebabe..3e096f2af 100644
--- a/Source/cmFunctionBlocker.h
+++ b/Source/cmFunctionBlocker.h
@@ -38,6 +38,8 @@ private:
virtual cm::string_view StartCommandName() const = 0;
virtual cm::string_view EndCommandName() const = 0;
+ virtual bool EndCommandSupportsArguments() const { return true; }
+
virtual bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const = 0;
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 1359009e6..f4768b66a 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -120,6 +120,7 @@ bool cmFunctionHelperCommand::operator()(
return false;
}
if (status.GetReturnInvoked()) {
+ makefile.RaiseScope(status.GetReturnVariables());
break;
}
}
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index b529b8f04..c72d6a7a8 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -14,11 +14,10 @@
#endif
cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
- : OriginalLocale(this->getloc())
{
#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
- this->imbue(std::locale(this->OriginalLocale, new codecvt(encoding)));
+ this->imbue(std::locale(this->getloc(), new codecvt(encoding)));
}
#else
static_cast<void>(encoding);
@@ -124,10 +123,10 @@ cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase()
void cmGeneratedFileStreamBase::Open(std::string const& name)
{
// Save the original name of the file.
- this->Name = name;
+ this->Name = cmSystemTools::CollapseFullPath(name);
// Create the name of the temporary file.
- this->TempName = name;
+ this->TempName = this->Name;
#if defined(__VMS)
this->TempName += "_";
#else
@@ -231,7 +230,7 @@ int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname,
void cmGeneratedFileStream::SetName(const std::string& fname)
{
- this->Name = fname;
+ this->Name = cmSystemTools::CollapseFullPath(fname);
}
void cmGeneratedFileStream::SetTempExt(std::string const& ext)
@@ -239,13 +238,16 @@ void cmGeneratedFileStream::SetTempExt(std::string const& ext)
this->TempExt = ext;
}
-void cmGeneratedFileStream::WriteRaw(std::string const& data)
+void cmGeneratedFileStream::WriteAltEncoding(std::string const& data,
+ Encoding encoding)
{
#ifndef CMAKE_BOOTSTRAP
- std::locale activeLocale = this->imbue(this->OriginalLocale);
+ std::locale prevLocale =
+ this->imbue(std::locale(this->getloc(), new codecvt(encoding)));
this->write(data.data(), data.size());
- this->imbue(activeLocale);
+ this->imbue(prevLocale);
#else
+ static_cast<void>(encoding);
this->write(data.data(), data.size());
#endif
}
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index bb7e3bf52..bfc121fb8 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -148,12 +148,8 @@ public:
void SetTempExt(std::string const& ext);
/**
- * Writes the given string directly to the file without changing the
- * encoding.
+ * Write a specific string using an alternate encoding.
+ * Afterward, the original encoding is restored.
*/
- void WriteRaw(std::string const& data);
-
-private:
- // The original locale of the stream (performs no encoding conversion).
- std::locale OriginalLocale;
+ void WriteAltEncoding(std::string const& data, Encoding encoding);
};
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 6235a2ae9..7d43eb139 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -808,11 +808,16 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
dagChecker, depTgt, language),
result);
}
- if (!depTgt->IsImported() || excludeImported) {
+ if (!depTgt->GetPropertyAsBool("SYSTEM")) {
return;
}
- if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
- return;
+ if (depTgt->IsImported()) {
+ if (excludeImported) {
+ return;
+ }
+ if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
+ return;
+ }
}
if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
@@ -912,11 +917,19 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
return false;
}
- if (lang != "C" && lang != "CXX" && lang != "Fortran") {
+ if (lang != "C" && lang != "CXX" && lang != "CUDA" && lang != "Fortran") {
// We do not define IPO behavior for other languages.
return false;
}
+ if (lang == "CUDA") {
+ // CUDA IPO requires both CUDA_ARCHITECTURES and CUDA_SEPARABLE_COMPILATION
+ if (cmIsOff(this->GetSafeProperty("CUDA_ARCHITECTURES")) ||
+ cmIsOff(this->GetSafeProperty("CUDA_SEPARABLE_COMPILATION"))) {
+ return false;
+ }
+ }
+
cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
@@ -1708,7 +1721,8 @@ void addFileSetEntry(cmGeneratorTarget const* headTarget,
}
}
if (!found) {
- if (fileSet->GetType() == "HEADERS"_s) {
+ if (fileSet->GetType() == "HEADERS"_s ||
+ fileSet->GetType() == "CXX_MODULE_HEADER_UNITS"_s) {
headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
->AddGroupFile(path);
}
@@ -1729,6 +1743,20 @@ void AddFileSetEntries(cmGeneratorTarget const* headTarget,
addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
}
}
+ for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
+ for (auto const& name : cmExpandedList(entry.Value)) {
+ auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries);
+ }
+ }
+ for (auto const& entry :
+ headTarget->Target->GetCxxModuleHeaderSetsEntries()) {
+ for (auto const& name : cmExpandedList(entry.Value)) {
+ auto const* cxxModuleHeaderSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, cxxModuleHeaderSet,
+ entries);
+ }
+ }
}
bool processSources(cmGeneratorTarget const* tgt,
@@ -3409,7 +3437,9 @@ void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
"EXPLICIT_LANGUAGE");
}
-void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
+void cmGeneratorTarget::AddCUDAArchitectureFlags(cmBuildStep compileOrLink,
+ const std::string& config,
+ std::string& flags) const
{
std::string property = this->GetSafeProperty("CUDA_ARCHITECTURES");
@@ -3441,6 +3471,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
std::string const& compiler =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
+ const bool ipoEnabled = this->IsIPOEnabled("CUDA", config);
// Check for special modes: `all`, `all-major`.
if (property == "all" || property == "all-major") {
@@ -3520,6 +3551,13 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
}
if (compiler == "NVIDIA") {
+ if (ipoEnabled && compileOrLink == cmBuildStep::Link) {
+ if (cmValue cudaIPOFlags =
+ this->Makefile->GetDefinition("CMAKE_CUDA_LINK_OPTIONS_IPO")) {
+ flags += cudaIPOFlags;
+ }
+ }
+
for (CudaArchitecture& architecture : architectures) {
flags +=
" --generate-code=arch=compute_" + architecture.name + ",code=[";
@@ -3532,7 +3570,13 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
}
}
- if (architecture.real) {
+ if (ipoEnabled) {
+ if (compileOrLink == cmBuildStep::Compile) {
+ flags += "lto_" + architecture.name;
+ } else if (compileOrLink == cmBuildStep::Link) {
+ flags += "sm_" + architecture.name;
+ }
+ } else if (architecture.real) {
flags += "sm_" + architecture.name;
}
@@ -5410,9 +5454,6 @@ std::string cmGeneratorTarget::GetObjectDirectory(
std::string obj_dir =
this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config);
#if defined(__APPLE__)
- // find and replace $(PROJECT_NAME) xcode placeholder
- const std::string projectName = this->LocalGenerator->GetProjectName();
- cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
// Replace Xcode's placeholder for the object file directory since
// installation and export scripts need to know the real directory.
// Xcode has build-time settings (e.g. for sanitizers) that affect this,
@@ -8719,8 +8760,92 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile(
cmGeneratedFileStream fout(filename);
fout.SetCopyIfDifferent(true);
- fout << "#include <" << headerFilename << ">\n";
+ // IWYU pragma: associated allows include what you use to
+ // consider the headerFile as part of the entire language
+ // unit within include-what-you-use and as a result allows
+ // one to get IWYU advice for headers :)
+ fout << "#include <" << headerFilename << "> // IWYU pragma: associated\n";
fout.close();
return filename;
}
+
+bool cmGeneratorTarget::HaveCxx20ModuleSources() const
+{
+ auto const& fs_names = this->Target->GetAllFileSetNames();
+ return std::any_of(fs_names.begin(), fs_names.end(),
+ [this](std::string const& name) -> bool {
+ auto const* file_set = this->Target->GetFileSet(name);
+ if (!file_set) {
+ this->Makefile->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", this->Target->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ return false;
+ }
+
+ auto const& fs_type = file_set->GetType();
+ return fs_type == "CXX_MODULES"_s ||
+ fs_type == "CXX_MODULE_HEADER_UNITS"_s;
+ });
+}
+
+cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
+ std::string const& config) const
+{
+ auto const* state = this->Makefile->GetState();
+ if (!state->GetLanguageEnabled("CXX")) {
+ return Cxx20SupportLevel::MissingCxx;
+ }
+ cmValue standardDefault =
+ this->Target->GetMakefile()->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+ if (standardDefault && !standardDefault->empty()) {
+ cmStandardLevelResolver standardResolver(this->Makefile);
+ if (!standardResolver.HaveStandardAvailable(this, "CXX", config,
+ "cxx_std_20")) {
+ return Cxx20SupportLevel::NoCxx20;
+ }
+ }
+ // Else, an empty CMAKE_CXX_STANDARD_DEFAULT means CMake does not detect and
+ // set a default standard level for this compiler, so assume all standards
+ // are available.
+ if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
+ return Cxx20SupportLevel::MissingExperimentalFlag;
+ }
+ return Cxx20SupportLevel::Supported;
+}
+
+void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const
+{
+ // Check for `CXX_MODULE*` file sets and a lack of support.
+ if (this->HaveCxx20ModuleSources()) {
+ switch (this->HaveCxxModuleSupport(config)) {
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GetName(),
+ "\" target has C++ module sources but the \"CXX\" language "
+ "has not been enabled"));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingExperimentalFlag:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GetName(),
+ "\" target has C++ module sources but its experimental "
+ "support has not been requested"));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "The \"", this->GetName(),
+ "\" target has C++ module sources but is not using at least "
+ "\"cxx_std_20\""));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::Supported:
+ // All is well.
+ break;
+ }
+ }
+}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 6bce7d2b2..25e6a81ea 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -23,6 +23,7 @@
#include "cmStateTypes.h"
#include "cmValue.h"
+enum class cmBuildStep;
class cmComputeLinkInformation;
class cmCustomCommand;
class cmGlobalGenerator;
@@ -471,7 +472,9 @@ public:
void AddExplicitLanguageFlags(std::string& flags,
cmSourceFile const& sf) const;
- void AddCUDAArchitectureFlags(std::string& flags) const;
+ void AddCUDAArchitectureFlags(cmBuildStep compileOrLink,
+ const std::string& config,
+ std::string& flags) const;
void AddCUDAToolkitFlags(std::string& flags) const;
void AddHIPArchitectureFlags(std::string& flags) const;
@@ -1196,4 +1199,34 @@ public:
bool operator()(cmGeneratorTarget const* t1,
cmGeneratorTarget const* t2) const;
};
+
+ // C++20 module support queries.
+
+ /**
+ * Query whether the target expects C++20 module support.
+ *
+ * This will inspect the target itself to see if C++20 module
+ * support is expected to work based on its sources.
+ */
+ bool HaveCxx20ModuleSources() const;
+
+ enum class Cxx20SupportLevel
+ {
+ // C++ is not available.
+ MissingCxx,
+ // The experimental feature is not available.
+ MissingExperimentalFlag,
+ // The target does not require at least C++20.
+ NoCxx20,
+ // C++20 modules are available and working.
+ Supported,
+ };
+ /**
+ * Query whether the target has C++20 module support available (regardless of
+ * whether it is required or not).
+ */
+ Cxx20SupportLevel HaveCxxModuleSupport(std::string const& config) const;
+
+ // Check C++ module status for the target.
+ void CheckCxxModuleStatus(std::string const& config) const;
};
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index bf019c35e..138d3f1c9 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -183,8 +183,8 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
auto i = this->FlagsByLanguage.find(language);
if (i == this->FlagsByLanguage.end()) {
std::string flags;
- this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
- language, config);
+ this->LocalGenerator->AddLanguageFlags(
+ flags, this->GeneratorTarget, cmBuildStep::Compile, language, config);
this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget,
language, config);
this->LocalGenerator->AddVisibilityPresetFlags(
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 0fe55f048..c2bf888d1 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2554,9 +2554,9 @@ bool cmGlobalGenerator::NameResolvesToFramework(
// This is where we change the path to point to the framework directory.
// .tbd files also can be located in SDK frameworks (they are
// placeholders for actual libraries shipped with the OS)
-cm::optional<std::pair<std::string, std::string>>
+cm::optional<cmGlobalGenerator::FrameworkDescriptor>
cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
- bool extendedFormat) const
+ FrameworkFormat format) const
{
// Check for framework structure:
// (/path/to/)?FwName.framework
@@ -2571,20 +2571,29 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
auto name = frameworkPath.match(3);
auto libname =
cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6));
+ if (format == FrameworkFormat::Strict && libname.empty()) {
+ return cm::nullopt;
+ }
if (!libname.empty() && !cmHasPrefix(libname, name)) {
return cm::nullopt;
}
- return std::pair<std::string, std::string>{ frameworkPath.match(2), name };
+
+ if (libname.empty() || name.size() == libname.size()) {
+ return FrameworkDescriptor{ frameworkPath.match(2), name };
+ }
+
+ return FrameworkDescriptor{ frameworkPath.match(2), name,
+ libname.substr(name.size()) };
}
- if (extendedFormat) {
+ if (format == FrameworkFormat::Extended) {
// path format can be more flexible: (/path/to/)?fwName(.framework)?
auto fwDir = cmSystemTools::GetParentDirectory(path);
auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework"
? cmSystemTools::GetFilenameWithoutExtension(path)
: cmSystemTools::GetFilenameName(path);
- return std::pair<std::string, std::string>{ fwDir, name };
+ return FrameworkDescriptor{ fwDir, name };
}
return cm::nullopt;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 6e3072bf5..89b2ea8d7 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -17,6 +17,7 @@
#include <cm/optional>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cm_codecvt.hxx"
@@ -367,13 +368,61 @@ public:
/** Determine if a name resolves to a framework on disk or a built target
that is a framework. */
bool NameResolvesToFramework(const std::string& libname) const;
- /** Split a framework path to the directory and name of the framework
- * returns std::nullopt if the path does not match with framework format
+ /** Split a framework path to the directory and name of the framework as well
+ * as optiona; suffix.
+ * Returns std::nullopt if the path does not match with framework format
* when extendedFormat is true, required format is relaxed (i.e. extension
* `.framework' is optional). Used when FRAMEWORK link feature is
* specified */
- cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath(
- const std::string& path, bool extendedFormat = false) const;
+ struct FrameworkDescriptor
+ {
+ FrameworkDescriptor(std::string directory, std::string name)
+ : Directory(std::move(directory))
+ , Name(std::move(name))
+ {
+ }
+ FrameworkDescriptor(std::string directory, std::string name,
+ std::string suffix)
+ : Directory(std::move(directory))
+ , Name(std::move(name))
+ , Suffix(std::move(suffix))
+ {
+ }
+ std::string GetLinkName() const
+ {
+ return this->Suffix.empty() ? this->Name
+ : cmStrCat(this->Name, ',', this->Suffix);
+ }
+ std::string GetFullName() const
+ {
+ return cmStrCat(this->Name, ".framework/"_s, this->Name, this->Suffix);
+ }
+ std::string GetFrameworkPath() const
+ {
+ return this->Directory.empty()
+ ? cmStrCat(this->Name, ".framework"_s)
+ : cmStrCat(this->Directory, '/', this->Name, ".framework"_s);
+ }
+ std::string GetFullPath() const
+ {
+ return this->Directory.empty()
+ ? this->GetFullName()
+ : cmStrCat(this->Directory, '/', this->GetFullName());
+ }
+
+ const std::string Directory;
+ const std::string Name;
+ const std::string Suffix;
+ };
+ enum class FrameworkFormat
+ {
+ Strict,
+ Relaxed,
+ Extended
+ };
+ cm::optional<FrameworkDescriptor> SplitFrameworkPath(
+ const std::string& path,
+ FrameworkFormat format = FrameworkFormat::Relaxed) const;
cmMakefile* FindMakefile(const std::string& start_dir) const;
cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 6248f09a5..077de42c4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -3,8 +3,10 @@
#include "cmGlobalNinjaGenerator.h"
#include <algorithm>
+#include <cassert>
#include <cctype>
#include <cstdio>
+#include <functional>
#include <sstream>
#include <utility>
@@ -14,6 +16,7 @@
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/memory>
+#include <cmext/string_view>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
@@ -21,7 +24,9 @@
#include "cmsys/FStream.hxx"
+#include "cmCxxModuleMapper.h"
#include "cmDocumentationEntry.h"
+#include "cmFileSet.h"
#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
@@ -2467,13 +2472,53 @@ cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
}
+struct CxxModuleFileSet
+{
+ std::string Name;
+ std::string RelativeDirectory;
+ std::string SourcePath;
+ std::string Type;
+ cmFileSetVisibility Visibility;
+ cm::optional<std::string> Destination;
+};
+
+struct CxxModuleBmiInstall
+{
+ std::string Component;
+ std::string Destination;
+ bool ExcludeFromAll;
+ bool Optional;
+ std::string Permissions;
+ std::string MessageLevel;
+ std::string ScriptLocation;
+};
+
+struct CxxModuleExport
+{
+ std::string Name;
+ std::string Destination;
+ std::string Prefix;
+ std::string CxxModuleInfoDir;
+ std::string Namespace;
+ bool Install;
+};
+
+struct cmGlobalNinjaGenerator::CxxModuleExportInfo
+{
+ std::map<std::string, CxxModuleFileSet> ObjectToFileSet;
+ cm::optional<CxxModuleBmiInstall> BmiInstallation;
+ std::vector<CxxModuleExport> Exports;
+ std::string Config;
+};
+
bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt)
+ std::string const& arg_lang, std::string const& arg_modmapfmt,
+ CxxModuleExportInfo const& export_info)
{
// Setup path conversions.
{
@@ -2498,13 +2543,15 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
objects.push_back(std::move(info));
}
+ CxxModuleUsage usages;
+
// Map from module name to module file path, if known.
std::map<std::string, std::string> mod_files;
// Populate the module map with those provided by linked targets first.
for (std::string const& linked_target_dir : linked_target_dirs) {
std::string const ltmn =
- cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json");
+ cmStrCat(linked_target_dir, '/', arg_lang, "Modules.json");
Json::Value ltm;
cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
@@ -2515,21 +2562,71 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
return false;
}
if (ltm.isObject()) {
- for (Json::Value::iterator i = ltm.begin(); i != ltm.end(); ++i) {
- mod_files[i.key().asString()] = i->asString();
+ Json::Value const& target_modules = ltm["modules"];
+ if (target_modules.isObject()) {
+ for (auto i = target_modules.begin(); i != target_modules.end(); ++i) {
+ mod_files[i.key().asString()] = i->asString();
+ }
+ }
+ Json::Value const& target_modules_references = ltm["references"];
+ if (target_modules_references.isObject()) {
+ for (auto i = target_modules_references.begin();
+ i != target_modules_references.end(); ++i) {
+ if (i->isObject()) {
+ Json::Value const& reference_path = (*i)["path"];
+ CxxModuleReference module_reference;
+ if (reference_path.isString()) {
+ module_reference.Path = reference_path.asString();
+ }
+ Json::Value const& reference_method = (*i)["lookup-method"];
+ if (reference_method.isString()) {
+ std::string reference = reference_method.asString();
+ if (reference == "by-name") {
+ module_reference.Method = LookupMethod::ByName;
+ } else if (reference == "include-angle") {
+ module_reference.Method = LookupMethod::IncludeAngle;
+ } else if (reference == "include-quote") {
+ module_reference.Method = LookupMethod::IncludeQuote;
+ }
+ }
+ usages.Reference[i.key().asString()] = module_reference;
+ }
+ }
+ }
+ Json::Value const& target_modules_usage = ltm["usages"];
+ if (target_modules_usage.isObject()) {
+ for (auto i = target_modules_usage.begin();
+ i != target_modules_usage.end(); ++i) {
+ if (i->isArray()) {
+ for (auto j = i->begin(); j != i->end(); ++j) {
+ usages.Usage[i.key().asString()].insert(j->asString());
+ }
+ }
+ }
}
}
}
- const char* module_ext = "";
- if (arg_modmapfmt == "gcc") {
- module_ext = ".gcm";
+ cm::optional<CxxModuleMapFormat> modmap_fmt;
+ if (arg_modmapfmt.empty()) {
+ // nothing to do.
+ } else if (arg_modmapfmt == "gcc") {
+ modmap_fmt = CxxModuleMapFormat::Gcc;
+ } else if (arg_modmapfmt == "msvc") {
+ modmap_fmt = CxxModuleMapFormat::Msvc;
+ } else {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep does not understand the ", arg_modmapfmt,
+ " module map format"));
+ return false;
}
+ auto module_ext = CxxModuleMapExtension(modmap_fmt);
+
// Extend the module map with those provided by this target.
// We do this after loading the modules provided by linked targets
// in case we have one of the same name that must be preferred.
- Json::Value tm = Json::objectValue;
+ Json::Value target_modules = Json::objectValue;
for (cmScanDepInfo const& object : objects) {
for (auto const& p : object.Provides) {
std::string mod;
@@ -2542,12 +2639,13 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
}
} else {
// Assume the module file path matches the logical module name.
- std::string safe_logical_name = p.LogicalName;
+ std::string safe_logical_name =
+ p.LogicalName; // TODO: needs fixing for header units
cmSystemTools::ReplaceString(safe_logical_name, ":", "-");
mod = cmStrCat(module_dir, safe_logical_name, module_ext);
}
mod_files[p.LogicalName] = mod;
- tm[p.LogicalName] = mod;
+ target_modules[p.LogicalName] = mod;
}
}
@@ -2555,6 +2653,32 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
ddf << "ninja_dyndep_version = 1.0\n";
{
+ CxxModuleLocations locs;
+ locs.RootDirectory = ".";
+ locs.PathForGenerator = [this](std::string const& path) -> std::string {
+ return this->ConvertToNinjaPath(path);
+ };
+ locs.BmiLocationForModule =
+ [&mod_files](std::string const& logical) -> cm::optional<std::string> {
+ auto m = mod_files.find(logical);
+ if (m != mod_files.end()) {
+ return m->second;
+ }
+ return {};
+ };
+
+ // Insert information about the current target's modules.
+ if (modmap_fmt) {
+ auto cycle_modules = CxxModuleUsageSeed(locs, objects, usages);
+ if (!cycle_modules.empty()) {
+ cmSystemTools::Error(
+ cmStrCat("Circular dependency detected in the C++ module import "
+ "graph. See modules named: \"",
+ cmJoin(cycle_modules, R"(", ")"_s), '"'));
+ return false;
+ }
+ }
+
cmNinjaBuild build("dyndep");
build.Outputs.emplace_back("");
for (cmScanDepInfo const& object : objects) {
@@ -2576,60 +2700,332 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Variables.emplace("restat", "1");
}
- if (arg_modmapfmt.empty()) {
- // nothing to do.
- } else {
- std::stringstream mm;
- if (arg_modmapfmt == "gcc") {
- // Documented in GCC's documentation. The format is a series of lines
- // with a module name and the associated filename separated by
- // spaces. The first line may use `$root` as the module name to
- // specify a "repository root". That is used to anchor any relative
- // paths present in the file (CMake should never generate any).
-
- // Write the root directory to use for module paths.
- mm << "$root .\n";
-
- for (auto const& l : object.Provides) {
- auto m = mod_files.find(l.LogicalName);
- if (m != mod_files.end()) {
- mm << l.LogicalName << " " << this->ConvertToNinjaPath(m->second)
- << "\n";
- }
- }
- for (auto const& r : object.Requires) {
- auto m = mod_files.find(r.LogicalName);
- if (m != mod_files.end()) {
- mm << r.LogicalName << " " << this->ConvertToNinjaPath(m->second)
- << "\n";
- }
- }
- } else {
- cmSystemTools::Error(
- cmStrCat("-E cmake_ninja_dyndep does not understand the ",
- arg_modmapfmt, " module map format"));
- return false;
- }
+ if (modmap_fmt) {
+ auto mm = CxxModuleMapContent(*modmap_fmt, locs, object, usages);
// XXX(modmap): If changing this path construction, change
// `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the
// corresponding file path.
cmGeneratedFileStream mmf(cmStrCat(object.PrimaryOutput, ".modmap"));
- mmf << mm.str();
+ mmf << mm;
}
this->WriteBuild(ddf, build);
}
}
+ Json::Value target_module_info = Json::objectValue;
+ target_module_info["modules"] = target_modules;
+
+ auto& target_usages = target_module_info["usages"] = Json::objectValue;
+ for (auto const& u : usages.Usage) {
+ auto& mod_usage = target_usages[u.first] = Json::arrayValue;
+ for (auto const& v : u.second) {
+ mod_usage.append(v);
+ }
+ }
+
+ auto name_for_method = [](LookupMethod method) -> cm::static_string_view {
+ switch (method) {
+ case LookupMethod::ByName:
+ return "by-name"_s;
+ case LookupMethod::IncludeAngle:
+ return "include-angle"_s;
+ case LookupMethod::IncludeQuote:
+ return "include-quote"_s;
+ }
+ assert(false && "unsupported lookup method");
+ return ""_s;
+ };
+
+ auto& target_references = target_module_info["references"] =
+ Json::objectValue;
+ for (auto const& r : usages.Reference) {
+ auto& mod_ref = target_references[r.first] = Json::objectValue;
+ mod_ref["path"] = r.second.Path;
+ mod_ref["lookup-method"] = std::string(name_for_method(r.second.Method));
+ }
+
// Store the map of modules provided by this target in a file for
// use by dependents that reference this target in linked-target-dirs.
std::string const target_mods_file = cmStrCat(
cmSystemTools::GetFilenamePath(arg_dd), '/', arg_lang, "Modules.json");
cmGeneratedFileStream tmf(target_mods_file);
- tmf << tm;
+ tmf << target_module_info;
+
+ bool result = true;
+
+ // Fortran doesn't support any of the file-set or BMI installation considered
+ // below.
+ if (arg_lang != "Fortran"_s) {
+ // Prepare the export information blocks.
+ std::string const config_upper =
+ cmSystemTools::UpperCase(export_info.Config);
+ std::vector<std::pair<std::unique_ptr<cmGeneratedFileStream>,
+ CxxModuleExport const*>>
+ exports;
+ for (auto const& exp : export_info.Exports) {
+ std::unique_ptr<cmGeneratedFileStream> properties;
+
+ std::string const export_dir =
+ cmStrCat(exp.Prefix, '/', exp.CxxModuleInfoDir, '/');
+ std::string const property_file_path = cmStrCat(
+ export_dir, "target-", exp.Name, '-', export_info.Config, ".cmake");
+ properties = cm::make_unique<cmGeneratedFileStream>(property_file_path);
+
+ // Set up the preamble.
+ *properties << "set_property(TARGET \"" << exp.Namespace << exp.Name
+ << "\"\n"
+ << " PROPERTY IMPORTED_CXX_MODULES_" << config_upper
+ << '\n';
+
+ exports.emplace_back(std::move(properties), &exp);
+ }
+
+ std::unique_ptr<cmGeneratedFileStream> bmi_install_script;
+ if (export_info.BmiInstallation) {
+ bmi_install_script = cm::make_unique<cmGeneratedFileStream>(
+ export_info.BmiInstallation->ScriptLocation);
+ }
+
+ auto cmEscape = [](cm::string_view str) {
+ return cmOutputConverter::EscapeForCMake(
+ str, cmOutputConverter::WrapQuotes::NoWrap);
+ };
+ auto install_destination =
+ [&cmEscape](std::string const& dest) -> std::pair<bool, std::string> {
+ if (cmSystemTools::FileIsFullPath(dest)) {
+ return std::make_pair(true, cmEscape(dest));
+ }
+ return std::make_pair(false,
+ cmStrCat("${_IMPORT_PREFIX}/", cmEscape(dest)));
+ };
- return true;
+ // public/private requirement tracking.
+ std::set<std::string> private_modules;
+ std::map<std::string, std::set<std::string>> public_source_requires;
+
+ for (cmScanDepInfo const& object : objects) {
+ // Convert to forward slashes.
+ auto output_path = object.PrimaryOutput;
+# ifdef _WIN32
+ cmSystemTools::ConvertToUnixSlashes(output_path);
+# endif
+ // Find the fileset for this object.
+ auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path);
+ bool const has_provides = !object.Provides.empty();
+ if (fileset_info_itr == export_info.ObjectToFileSet.end()) {
+ // If it provides anything, it should have a `CXX_MODULES` or
+ // `CXX_MODULE_INTERNAL_PARTITIONS` type and be present.
+ if (has_provides) {
+ // Take the first module provided to provide context.
+ auto const& provides = object.Provides[0];
+ char const* ok_types = "`CXX_MODULES`";
+ if (provides.LogicalName.find(':') != std::string::npos) {
+ ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if "
+ "it is not `export`ed)";
+ }
+ cmSystemTools::Error(
+ cmStrCat("Output ", object.PrimaryOutput, " provides the `",
+ provides.LogicalName,
+ "` module but it is not found in a `FILE_SET` of type ",
+ ok_types));
+ result = false;
+ }
+
+ // This object file does not provide anything, so nothing more needs to
+ // be done.
+ continue;
+ }
+
+ auto const& file_set = fileset_info_itr->second;
+
+ // Verify the fileset type for the object.
+ if (file_set.Type == "CXX_MODULES"_s) {
+ if (!has_provides) {
+ cmSystemTools::Error(cmStrCat(
+ "Output ", object.PrimaryOutput,
+ " is of type `CXX_MODULES` but does not provide a module"));
+ result = false;
+ continue;
+ }
+ } else if (file_set.Type == "CXX_MODULE_INTERNAL_PARTITIONS"_s) {
+ if (!has_provides) {
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath,
+ " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not "
+ "provide a module"));
+ result = false;
+ continue;
+ }
+ auto const& provides = object.Provides[0];
+ if (provides.LogicalName.find(':') == std::string::npos) {
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath,
+ " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not "
+ "provide a module partition"));
+ result = false;
+ continue;
+ }
+ } else if (file_set.Type == "CXX_MODULE_HEADERS"_s) {
+ // TODO.
+ } else {
+ if (has_provides) {
+ auto const& provides = object.Provides[0];
+ char const* ok_types = "`CXX_MODULES`";
+ if (provides.LogicalName.find(':') != std::string::npos) {
+ ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if "
+ "it is not `export`ed)";
+ }
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath, " provides the `",
+ provides.LogicalName, "` C++ module but is of type `",
+ file_set.Type, "` module but must be of type ", ok_types));
+ result = false;
+ }
+
+ // Not a C++ module; ignore.
+ continue;
+ }
+
+ if (!cmFileSetVisibilityIsForInterface(file_set.Visibility)) {
+ // Nothing needs to be conveyed about non-`PUBLIC` modules.
+ for (auto const& p : object.Provides) {
+ private_modules.insert(p.LogicalName);
+ }
+ continue;
+ }
+
+ // The module is public. Record what it directly requires.
+ {
+ auto& reqs = public_source_requires[file_set.SourcePath];
+ for (auto const& r : object.Requires) {
+ reqs.insert(r.LogicalName);
+ }
+ }
+
+ // Write out properties and install rules for any exports.
+ for (auto const& p : object.Provides) {
+ bool bmi_dest_is_abs = false;
+ std::string bmi_destination;
+ if (export_info.BmiInstallation) {
+ auto dest =
+ install_destination(export_info.BmiInstallation->Destination);
+ bmi_dest_is_abs = dest.first;
+ bmi_destination = cmStrCat(dest.second, '/');
+ }
+
+ std::string install_bmi_path;
+ std::string build_bmi_path;
+ auto m = mod_files.find(p.LogicalName);
+ if (m != mod_files.end()) {
+ install_bmi_path =
+ cmStrCat(bmi_destination,
+ cmEscape(cmSystemTools::GetFilenameName(m->second)));
+ build_bmi_path = cmEscape(m->second);
+ }
+
+ for (auto const& exp : exports) {
+ std::string iface_source;
+ if (exp.second->Install && file_set.Destination) {
+ auto dest = install_destination(*file_set.Destination);
+ iface_source = cmStrCat(
+ dest.second, '/', cmEscape(file_set.RelativeDirectory),
+ cmEscape(cmSystemTools::GetFilenameName(file_set.SourcePath)));
+ } else {
+ iface_source = cmEscape(file_set.SourcePath);
+ }
+
+ std::string bmi_path;
+ if (exp.second->Install && export_info.BmiInstallation) {
+ bmi_path = install_bmi_path;
+ } else if (!exp.second->Install) {
+ bmi_path = build_bmi_path;
+ }
+
+ if (iface_source.empty()) {
+ // No destination for the C++ module source; ignore this property
+ // value.
+ continue;
+ }
+
+ *exp.first << " \"" << cmEscape(p.LogicalName) << '='
+ << iface_source;
+ if (!bmi_path.empty()) {
+ *exp.first << ',' << bmi_path;
+ }
+ *exp.first << "\"\n";
+ }
+
+ if (bmi_install_script) {
+ auto const& bmi_install = *export_info.BmiInstallation;
+
+ *bmi_install_script << "if (CMAKE_INSTALL_COMPONENT STREQUAL \""
+ << cmEscape(bmi_install.Component) << '\"';
+ if (!bmi_install.ExcludeFromAll) {
+ *bmi_install_script << " OR NOT CMAKE_INSTALL_COMPONENT";
+ }
+ *bmi_install_script << ")\n";
+ *bmi_install_script << " file(INSTALL\n"
+ " DESTINATION \"";
+ if (!bmi_dest_is_abs) {
+ *bmi_install_script << "${CMAKE_INSTALL_PREFIX}/";
+ }
+ *bmi_install_script << cmEscape(bmi_install.Destination)
+ << "\"\n"
+ " TYPE FILE\n";
+ if (bmi_install.Optional) {
+ *bmi_install_script << " OPTIONAL\n";
+ }
+ if (!bmi_install.MessageLevel.empty()) {
+ *bmi_install_script << " " << bmi_install.MessageLevel << "\n";
+ }
+ if (!bmi_install.Permissions.empty()) {
+ *bmi_install_script << " PERMISSIONS" << bmi_install.Permissions
+ << "\n";
+ }
+ *bmi_install_script << " FILES \"" << m->second << "\")\n";
+ if (bmi_dest_is_abs) {
+ *bmi_install_script
+ << " list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n"
+ " \""
+ << cmEscape(cmSystemTools::GetFilenameName(m->second))
+ << "\")\n"
+ " if (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n"
+ " message(WARNING\n"
+ " \"ABSOLUTE path INSTALL DESTINATION : "
+ "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"
+ " endif ()\n"
+ " if (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n"
+ " message(FATAL_ERROR\n"
+ " \"ABSOLUTE path INSTALL DESTINATION forbidden (by "
+ "caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"
+ " endif ()\n";
+ }
+ *bmi_install_script << "endif ()\n";
+ }
+ }
+ }
+
+ // Add trailing parenthesis for the `set_property` call.
+ for (auto const& exp : exports) {
+ *exp.first << ")\n";
+ }
+
+ // Check that public sources only require public modules.
+ for (auto const& pub_reqs : public_source_requires) {
+ for (auto const& req : pub_reqs.second) {
+ if (private_modules.count(req)) {
+ cmSystemTools::Error(cmStrCat(
+ "Public C++ module source `", pub_reqs.first, "` requires the `",
+ req, "` C++ module which is provided by a private source"));
+ result = false;
+ }
+ }
+ }
+ }
+
+ return result;
}
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
@@ -2703,6 +3099,59 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
}
}
+ cmGlobalNinjaGenerator::CxxModuleExportInfo export_info;
+ export_info.Config = tdi["config"].asString();
+ if (export_info.Config.empty()) {
+ export_info.Config = "noconfig";
+ }
+ Json::Value const& tdi_exports = tdi["exports"];
+ if (tdi_exports.isArray()) {
+ for (auto const& tdi_export : tdi_exports) {
+ CxxModuleExport exp;
+ exp.Install = tdi_export["install"].asBool();
+ exp.Name = tdi_export["export-name"].asString();
+ exp.Destination = tdi_export["destination"].asString();
+ exp.Prefix = tdi_export["export-prefix"].asString();
+ exp.CxxModuleInfoDir = tdi_export["cxx-module-info-dir"].asString();
+ exp.Namespace = tdi_export["namespace"].asString();
+
+ export_info.Exports.push_back(exp);
+ }
+ }
+ auto const& bmi_installation = tdi["bmi-installation"];
+ if (bmi_installation.isObject()) {
+ CxxModuleBmiInstall bmi_install;
+
+ bmi_install.Component = bmi_installation["component"].asString();
+ bmi_install.Destination = bmi_installation["destination"].asString();
+ bmi_install.ExcludeFromAll = bmi_installation["exclude-from-all"].asBool();
+ bmi_install.Optional = bmi_installation["optional"].asBool();
+ bmi_install.Permissions = bmi_installation["permissions"].asString();
+ bmi_install.MessageLevel = bmi_installation["message-level"].asString();
+ bmi_install.ScriptLocation =
+ bmi_installation["script-location"].asString();
+
+ export_info.BmiInstallation = bmi_install;
+ }
+ Json::Value const& tdi_cxx_modules = tdi["cxx-modules"];
+ if (tdi_cxx_modules.isObject()) {
+ for (auto i = tdi_cxx_modules.begin(); i != tdi_cxx_modules.end(); ++i) {
+ CxxModuleFileSet& fsi = export_info.ObjectToFileSet[i.key().asString()];
+ auto const& tdi_cxx_module_info = *i;
+ fsi.Name = tdi_cxx_module_info["name"].asString();
+ fsi.RelativeDirectory =
+ tdi_cxx_module_info["relative-directory"].asString();
+ fsi.SourcePath = tdi_cxx_module_info["source"].asString();
+ fsi.Type = tdi_cxx_module_info["type"].asString();
+ fsi.Visibility = cmFileSetVisibilityFromName(
+ tdi_cxx_module_info["visibility"].asString(), nullptr);
+ auto const& tdi_fs_dest = tdi_cxx_module_info["destination"];
+ if (tdi_fs_dest.isString()) {
+ fsi.Destination = tdi_fs_dest.asString();
+ }
+ }
+ }
+
cmake cm(cmake::RoleInternal, cmState::Unknown);
cm.SetHomeDirectory(dir_top_src);
cm.SetHomeOutputDirectory(dir_top_bld);
@@ -2710,7 +3159,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
if (!ggd ||
!cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile(
dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis,
- module_dir, linked_target_dirs, arg_lang, arg_modmapfmt)) {
+ module_dir, linked_target_dirs, arg_lang, arg_modmapfmt,
+ export_info)) {
return 1;
}
return 0;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 03387a88f..defa2645c 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -417,13 +417,15 @@ public:
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
+ struct CxxModuleExportInfo;
bool WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt);
+ std::string const& arg_lang, std::string const& arg_modmapfmt,
+ CxxModuleExportInfo const& export_info);
virtual std::string BuildAlias(const std::string& alias,
const std::string& /*config*/) const
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 29eeb5a91..bea2ae7e2 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -20,7 +20,6 @@
#include "cmDocumentationEntry.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudio71Generator.h"
#include "cmGlobalVisualStudio7Generator.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -38,7 +37,6 @@
#include "cmXMLWriter.h"
#include "cmake.h"
-static const char vs10generatorName[] = "Visual Studio 10 2010";
static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;
static void ConvertToWindowsSlashes(std::string& s)
@@ -51,137 +49,14 @@ static void ConvertToWindowsSlashes(std::string& s)
}
}
-// Map generator name without year to name with year.
-static const char* cmVS10GenName(const std::string& name, std::string& genName)
-{
- if (strncmp(name.c_str(), vs10generatorName,
- sizeof(vs10generatorName) - 6) != 0) {
- return 0;
- }
- const char* p = name.c_str() + sizeof(vs10generatorName) - 6;
- if (cmHasLiteralPrefix(p, " 2010")) {
- p += 5;
- }
- genName = std::string(vs10generatorName) + p;
- return p;
-}
-
-class cmGlobalVisualStudio10Generator::Factory
- : public cmGlobalGeneratorFactory
-{
-public:
- std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, bool allowArch, cmake* cm) const override
- {
- std::string genName;
- const char* p = cmVS10GenName(name, genName);
- if (!p) {
- return std::unique_ptr<cmGlobalGenerator>();
- }
- if (!*p) {
- return std::unique_ptr<cmGlobalGenerator>(
- new cmGlobalVisualStudio10Generator(cm, genName, ""));
- }
- if (!allowArch || *p++ != ' ') {
- return std::unique_ptr<cmGlobalGenerator>();
- }
- if (strcmp(p, "Win64") == 0) {
- return std::unique_ptr<cmGlobalGenerator>(
- new cmGlobalVisualStudio10Generator(cm, genName, "x64"));
- }
- if (strcmp(p, "IA64") == 0) {
- return std::unique_ptr<cmGlobalGenerator>(
- new cmGlobalVisualStudio10Generator(cm, genName, "Itanium"));
- }
- return std::unique_ptr<cmGlobalGenerator>();
- }
-
- void GetDocumentation(cmDocumentationEntry& entry) const override
- {
- entry.Name = std::string(vs10generatorName) + " [arch]";
- entry.Brief = "Deprecated. Generates Visual Studio 2010 project files. "
- "Optional [arch] can be \"Win64\" or \"IA64\".";
- }
-
- std::vector<std::string> GetGeneratorNames() const override
- {
- std::vector<std::string> names;
- names.push_back(vs10generatorName);
- return names;
- }
-
- std::vector<std::string> GetGeneratorNamesWithPlatform() const override
- {
- std::vector<std::string> names;
- names.push_back(vs10generatorName + std::string(" IA64"));
- names.push_back(vs10generatorName + std::string(" Win64"));
- return names;
- }
-
- bool SupportsToolset() const override { return true; }
- bool SupportsPlatform() const override { return true; }
-
- std::vector<std::string> GetKnownPlatforms() const override
- {
- std::vector<std::string> platforms;
- platforms.emplace_back("x64");
- platforms.emplace_back("Win32");
- platforms.emplace_back("Itanium");
- return platforms;
- }
-
- std::string GetDefaultPlatformName() const override { return "Win32"; }
-};
-
-std::unique_ptr<cmGlobalGeneratorFactory>
-cmGlobalVisualStudio10Generator::NewFactory()
-{
- return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory);
-}
-
cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
cmake* cm, const std::string& name,
std::string const& platformInGeneratorName)
: cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName)
{
- std::string vc10Express;
- this->ExpressEdition = cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
- "ProductDir",
- vc10Express, cmSystemTools::KeyWOW64_32);
- this->CudaEnabled = false;
- {
- std::string envPlatformToolset;
- if (cmSystemTools::GetEnv("PlatformToolset", envPlatformToolset) &&
- envPlatformToolset == "Windows7.1SDK") {
- // We are running from a Windows7.1SDK command prompt.
- this->DefaultPlatformToolset = "Windows7.1SDK";
- } else {
- this->DefaultPlatformToolset = "v100";
- }
- }
- this->DefaultCLFlagTableName = "v10";
- this->DefaultCSharpFlagTableName = "v10";
- this->DefaultLibFlagTableName = "v10";
- this->DefaultLinkFlagTableName = "v10";
this->DefaultCudaFlagTableName = "v10";
this->DefaultCudaHostFlagTableName = "v10";
- this->DefaultMasmFlagTableName = "v10";
this->DefaultNasmFlagTableName = "v10";
- this->DefaultRCFlagTableName = "v10";
-
- this->Version = VSVersion::VS10;
- this->PlatformToolsetNeedsDebugEnum = false;
-}
-
-bool cmGlobalVisualStudio10Generator::MatchesGeneratorName(
- const std::string& name) const
-{
- std::string genName;
- if (cmVS10GenName(name, genName)) {
- return genName == this->GetName();
- }
- return false;
}
bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s,
@@ -195,21 +70,6 @@ bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s,
return this->cmGlobalVisualStudio8Generator::SetSystemName(s, mf);
}
-bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform(
- std::string const& p, cmMakefile* mf)
-{
- if (!this->cmGlobalVisualStudio8Generator::SetGeneratorPlatform(p, mf)) {
- return false;
- }
- if (this->GetPlatformName() == "Itanium" ||
- this->GetPlatformName() == "x64") {
- if (this->IsExpressEdition() && !this->Find64BitTools(mf)) {
- return false;
- }
- }
- return true;
-}
-
static void cmCudaToolVersion(std::string& s)
{
// "CUDA x.y.props" => "x.y"
@@ -389,6 +249,27 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
this->GeneratorToolsetVersion.clear();
this->GeneratorToolsetVersionProps = {};
} break;
+ case AuxToolset::PropsIndeterminate: {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset and version specification\n"
+ " " << this->GetPlatformToolsetString() << ",version=" <<
+ this->GeneratorToolsetVersion << "\n"
+ "has multiple matches installed at\n" <<
+ " " << auxProps << "\n" <<
+ "The toolset and version specification must resolve \n" <<
+ "to a single installed toolset";
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetVersion.clear();
+ this->GeneratorToolsetVersionProps = {};
+ } break;
}
}
@@ -1286,44 +1167,6 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
return makeCommands;
}
-bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
-{
- if (this->DefaultPlatformToolset == "v100") {
- // The v100 64-bit toolset does not exist in the express edition.
- this->DefaultPlatformToolset.clear();
- }
- if (this->GetPlatformToolset()) {
- return true;
- }
- // This edition does not come with 64-bit tools. Look for them.
- //
- // TODO: Detect available tools? x64\v100 exists but does not work?
- // HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath
- // c:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/
- // {Itanium,Win32,x64}/PlatformToolsets/{v100,v90,Windows7.1SDK}
- std::string winSDK_7_1;
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\"
- "Windows\\v7.1;InstallationFolder",
- winSDK_7_1)) {
- std::ostringstream m;
- m << "Found Windows SDK v7.1: " << winSDK_7_1;
- mf->DisplayStatus(m.str(), -1);
- this->DefaultPlatformToolset = "Windows7.1SDK";
- return true;
- } else {
- std::ostringstream e;
- /* clang-format off */
- e << "Cannot enable 64-bit tools with Visual Studio 2010 Express.\n"
- << "Install the Microsoft Windows SDK v7.1 to get 64-bit tools:\n"
- << " http://msdn.microsoft.com/en-us/windows/bb980924.aspx";
- /* clang-format on */
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str());
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
-}
-
std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
std::string const& output) const
{
@@ -1361,7 +1204,6 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const
{
switch (this->Version) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "4.0";
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 4977a845d..b32c0a795 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -14,7 +14,6 @@
#include "cmGlobalVisualStudio8Generator.h"
class cmGeneratorTarget;
-class cmGlobalGeneratorFactory;
class cmLocalGenerator;
class cmMakefile;
class cmSourceFile;
@@ -29,14 +28,9 @@ struct cmIDEFlagTable;
class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator
{
public:
- static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory();
-
bool IsVisualStudioAtLeast10() const override { return true; }
- bool MatchesGeneratorName(const std::string& name) const override;
-
bool SetSystemName(std::string const& s, cmMakefile* mf) override;
- bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
bool SetGeneratorToolset(std::string const& ts, bool build,
cmMakefile* mf) override;
@@ -131,7 +125,6 @@ public:
bool TargetsAndroid() const { return this->SystemIsAndroid; }
const char* GetCMakeCFGIntDir() const override { return "$(Configuration)"; }
- bool Find64BitTools(cmMakefile* mf);
/** Generate an <output>.rule file path for a given command output. */
std::string GenerateRuleFile(std::string const& output) const override;
@@ -200,7 +193,8 @@ protected:
None,
Default,
PropsExist,
- PropsMissing
+ PropsMissing,
+ PropsIndeterminate
};
virtual AuxToolset FindAuxToolset(std::string& version,
std::string& props) const;
@@ -243,9 +237,6 @@ protected:
bool MSBuildCommandInitialized = false;
private:
- class Factory;
- friend class Factory;
-
struct LongestSourcePath
{
LongestSourcePath()
@@ -269,7 +260,7 @@ private:
std::string GeneratorToolsetVersion;
- bool PlatformToolsetNeedsDebugEnum;
+ bool PlatformToolsetNeedsDebugEnum = false;
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
@@ -290,7 +281,7 @@ private:
std::string VCTargetsPath;
bool FindVCTargetsPath(cmMakefile* mf);
- bool CudaEnabled;
+ bool CudaEnabled = false;
// We do not use the reload macros for VS >= 10.
std::string GetUserMacrosDirectory() override { return ""; }
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 10dc25808..086d3afe5 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -77,7 +77,7 @@ public:
void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs11generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2012 project files. "
+ entry.Brief = "Deprecated. Generates Visual Studio 2012 project files. "
"Optional [arch] can be \"Win64\" or \"ARM\".";
}
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index f7f7317cd..ff76762cf 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -304,23 +304,23 @@ void cmGlobalVisualStudio7Generator::Generate()
GetSLNFile(this->LocalGenerators[0].get()));
}
- if (this->Version == VSVersion::VS10 &&
+ if (this->Version == VSVersion::VS11 &&
!this->CMakeInstance->GetIsInTryCompile()) {
- std::string cmakeWarnVS10;
+ std::string cmakeWarnVS11;
if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
- "CMAKE_WARN_VS10")) {
- this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10");
- cmakeWarnVS10 = *cached;
+ "CMAKE_WARN_VS11")) {
+ this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS11");
+ cmakeWarnVS11 = *cached;
} else {
- cmSystemTools::GetEnv("CMAKE_WARN_VS10", cmakeWarnVS10);
+ cmSystemTools::GetEnv("CMAKE_WARN_VS11", cmakeWarnVS11);
}
- if (cmakeWarnVS10.empty() || !cmIsOff(cmakeWarnVS10)) {
+ if (cmakeWarnVS11.empty() || !cmIsOff(cmakeWarnVS11)) {
this->CMakeInstance->IssueMessage(
MessageType::WARNING,
- "The \"Visual Studio 10 2010\" generator is deprecated "
+ "The \"Visual Studio 11 2012\" generator is deprecated "
"and will be removed in a future version of CMake."
"\n"
- "Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.");
+ "Add CMAKE_WARN_VS11=OFF to the cache to disable this warning.");
}
}
}
@@ -395,12 +395,27 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
{
VisualStudioFolders.clear();
+ std::vector<std::string> configs =
+ root->GetMakefile()->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
+
for (cmGeneratorTarget const* target : projectTargets) {
if (!this->IsInSolution(target)) {
continue;
}
bool written = false;
+ for (auto const& c : configs) {
+ target->CheckCxxModuleStatus(c);
+ }
+
+ if (target->HaveCxx20ModuleSources() && !this->SupportsCxxModuleDyndep()) {
+ root->GetMakefile()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", target->GetName(),
+ "\" target contains C++ module sources which are not "
+ "supported by the generator"));
+ }
+
// handle external vc project files
cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT");
if (expath) {
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index a55cf45c8..288069c77 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -157,6 +157,8 @@ protected:
cmValue typeGuid,
const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0;
+ virtual bool SupportsCxxModuleDyndep() const { return false; }
+
std::string ConvertToSolutionPath(const std::string& path);
std::set<std::string> IsPartOfDefaultBuild(
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index c6af20ad6..9d168d0e1 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -99,8 +99,6 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const
switch (this->Version) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return "9.0";
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
- return "10.0";
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "11.0";
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
@@ -128,14 +126,6 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n";
fout << "# Visual Studio 2008\n";
break;
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
- fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual C++ Express 2010\n";
- } else {
- fout << "# Visual Studio 2010\n";
- }
- break;
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
@@ -630,7 +620,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
RegCloseKey(hsubkey);
} else {
- std::cout << "error opening subkey: " << subkeyname << std::endl;
+ std::cout << "error opening subkey: "
+ << cmsys::Encoding::ToNarrow(subkeyname) << std::endl;
std::cout << std::endl;
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index f45b4d49a..576e4f2ff 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -35,7 +35,6 @@ public:
enum class VSVersion : uint16_t
{
VS9 = 90,
- VS10 = 100,
VS11 = 110,
VS12 = 120,
/* VS13 = 130 was skipped */
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 7e3688193..be318c178 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -127,8 +127,6 @@ static unsigned int VSVersionToMajor(
switch (v) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return 9;
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
- return 10;
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return 11;
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
@@ -151,8 +149,6 @@ static const char* VSVersionToToolset(
switch (v) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return "v90";
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
- return "v100";
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "v110";
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
@@ -175,8 +171,6 @@ static std::string VSVersionToMajorString(
switch (v) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return "9";
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
- return "10";
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "11";
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
@@ -198,7 +192,6 @@ static const char* VSVersionToAndroidToolset(
{
switch (v) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "";
@@ -500,7 +493,6 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
std::string genName;
switch (this->Version) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
case cmGlobalVisualStudioGenerator::VSVersion::VS14:
@@ -743,7 +735,6 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
{
switch (this->Version) {
case cmGlobalVisualStudioGenerator::VSVersion::VS9:
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "";
@@ -770,12 +761,15 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
cmSystemTools::ConvertToUnixSlashes(instancePath);
// Translate three-component format accepted by "vcvarsall -vcvars_ver=".
- cmsys::RegularExpression threeComponent(
+ cmsys::RegularExpression threeComponentRegex(
"^([0-9]+\\.[0-9]+)\\.[0-9][0-9][0-9][0-9][0-9]$");
- if (threeComponent.find(version)) {
+ // The two-component format represents the two major components of the
+ // three-component format
+ cmsys::RegularExpression twoComponentRegex("^([0-9]+\\.[0-9]+)$");
+ if (threeComponentRegex.find(version)) {
// Load "VC/Auxiliary/Build/*/Microsoft.VCToolsVersion.*.txt" files
// with two matching components to check their three-component version.
- std::string const& twoComponent = threeComponent.match(1);
+ std::string const& twoComponent = threeComponentRegex.match(1);
std::string pattern =
cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent,
"*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s);
@@ -801,6 +795,36 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
}
}
}
+ } else if (twoComponentRegex.find(version)) {
+ std::string const& twoComponent = twoComponentRegex.match(1);
+ std::string pattern =
+ cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent,
+ "*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s);
+ cmsys::Glob glob;
+ glob.SetRecurseThroughSymlinks(false);
+ if (glob.FindFiles(pattern) && !glob.GetFiles().empty()) {
+ // Since we are only using the first two components of the
+ // toolset version, we require a single match.
+ if (glob.GetFiles().size() == 1) {
+ std::string const& txt = glob.GetFiles()[0];
+ std::string ver;
+ cmsys::ifstream fin(txt.c_str());
+ if (fin && std::getline(fin, ver)) {
+ // Strip trailing whitespace.
+ ver = ver.substr(0, ver.find_first_not_of("0123456789."));
+ // We assume the version is correct, since it is the only one that
+ // matched.
+ cmsys::RegularExpression extractVersion(
+ "VCToolsVersion\\.([0-9.]+)\\.txt$");
+ if (extractVersion.find(txt)) {
+ version = extractVersion.match(1);
+ }
+ }
+ } else {
+ props = cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s);
+ return AuxToolset::PropsIndeterminate;
+ }
+ }
}
if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 23c365a4f..065802166 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -468,6 +468,10 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
}
CFRelease(cfStr);
}
+#else
+ (void)bindir;
+ (void)projectName;
+ (void)dryRun;
#endif
return ret;
@@ -603,7 +607,6 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
}
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
-#define OBJECT_LIBRARY_ARTIFACT_DIR std::string()
void cmGlobalXCodeGenerator::AddExtraTargets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
@@ -1188,13 +1191,9 @@ std::string GetTargetObjectDirArch(T const& target,
std::string cmGlobalXCodeGenerator::GetLibraryOrFrameworkPath(
const std::string& path) const
{
- auto fwItems = this->SplitFrameworkPath(path);
- if (fwItems) {
- if (fwItems->first.empty()) {
- return cmStrCat(fwItems->second, ".framework");
- } else {
- return cmStrCat(fwItems->first, '/', fwItems->second, ".framework");
- }
+ auto fwDescriptor = this->SplitFrameworkPath(path);
+ if (fwDescriptor) {
+ return fwDescriptor->GetFrameworkPath();
}
return path;
@@ -1372,6 +1371,18 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
return true;
}
+ for (std::string const& configName : this->CurrentConfigurationTypes) {
+ gtgt->CheckCxxModuleStatus(configName);
+ }
+
+ if (gtgt->HaveCxx20ModuleSources()) {
+ gtgt->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", gtgt->GetName(),
+ "\" target contains C++ module sources which are not "
+ "supported by the generator"));
+ }
+
auto& gtgt_visited = this->CommandsVisited[gtgt];
auto& deps = this->GetTargetDirectDepends(gtgt);
for (auto& d : deps) {
@@ -2352,8 +2363,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string& flags = cflags[lang];
// Add language-specific flags.
- this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
- configName);
+ this->CurrentLocalGenerator->AddLanguageFlags(
+ flags, gtgt, cmBuildStep::Compile, lang, configName);
if (gtgt->IsIPOEnabled(lang, configName)) {
this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
@@ -2376,7 +2387,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
gtgt->GetName());
return;
}
- std::string const& langForPreprocessor = llang;
+
+ // Choose a language to use for target-wide preprocessor definitions.
+ static const char* ppLangs[] = { "CXX", "C", "OBJCXX", "OBJC" };
+ std::string langForPreprocessorDefinitions;
+ if (cm::contains(ppLangs, llang)) {
+ langForPreprocessorDefinitions = llang;
+ } else {
+ for (const char* l : ppLangs) {
+ if (languages.count(l)) {
+ langForPreprocessorDefinitions = l;
+ break;
+ }
+ }
+ }
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
@@ -2393,25 +2417,45 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// Add preprocessor definitions for this target and configuration.
BuildObjectListOrString ppDefs(this, true);
- if (languages.count("Swift")) {
- // FIXME: Xcode warns that Swift does not support definition values.
- // C/CXX sources mixed in Swift targets will not see CMAKE_INTDIR.
- } else {
- this->AppendDefines(
- ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
- }
+ this->AppendDefines(
+ ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro->c_str());
}
std::vector<std::string> targetDefines;
- if (!langForPreprocessor.empty()) {
+ if (!langForPreprocessorDefinitions.empty()) {
gtgt->GetCompileDefinitions(targetDefines, configName,
- langForPreprocessor);
+ langForPreprocessorDefinitions);
}
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
+ if (languages.count("Swift")) {
+ // Swift uses a separate attribute for definitions.
+ std::vector<std::string> targetSwiftDefines;
+ gtgt->GetCompileDefinitions(targetSwiftDefines, configName, "Swift");
+ // Remove the '=value' parts, as Swift does not support them.
+ std::for_each(targetSwiftDefines.begin(), targetSwiftDefines.end(),
+ [](std::string& def) {
+ std::string::size_type pos = def.find('=');
+ if (pos != std::string::npos) {
+ def.erase(pos);
+ }
+ });
+ if (this->XcodeVersion < 80) {
+ std::string defineString;
+ std::set<std::string> defines(targetSwiftDefines.begin(),
+ targetSwiftDefines.end());
+ this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift");
+ cflags["Swift"] += " " + defineString;
+ } else {
+ BuildObjectListOrString swiftDefs(this, true);
+ this->AppendDefines(swiftDefs, targetSwiftDefines);
+ buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS",
+ swiftDefs.CreateList());
+ }
+ }
std::string extraLinkOptionsVar;
std::string extraLinkOptions;
@@ -2499,18 +2543,28 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
soName += *soversion;
}
+ if (gtgt->CanCompileSources()) {
+ std::string const tmpDir =
+ this->GetTargetTempDir(gtgt, this->GetCMakeCFGIntDir());
+ buildSettings->AddAttribute("TARGET_TEMP_DIR", this->CreateString(tmpDir));
+
+ std::string outDir;
+ if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // We cannot suppress the archive, so hide it with intermediate files.
+ outDir = tmpDir;
+ } else {
+ outDir = gtgt->GetDirectory(configName);
+ }
+ buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+ this->CreateString(outDir));
+ }
+
// Set attributes to specify the proper name for the target.
std::string pndir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
if (gtgt->GetType() == cmStateEnums::STATIC_LIBRARY ||
gtgt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gtgt->GetType() == cmStateEnums::MODULE_LIBRARY ||
gtgt->GetType() == cmStateEnums::EXECUTABLE) {
- if (!gtgt->UsesDefaultOutputDir(configName,
- cmStateEnums::RuntimeBinaryArtifact)) {
- std::string pncdir = gtgt->GetDirectory(configName);
- buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
- this->CreateString(pncdir));
- }
if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) {
pnprefix = "";
@@ -2520,20 +2574,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->CreateString(pnprefix));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
this->CreateString(pnsuffix));
- } else if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- pnprefix = "lib";
- pnbase = gtgt->GetName();
- pnsuffix = ".a";
-
- std::string pncdir = this->GetObjectsDirectory(
- this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR);
- buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
- this->CreateString(pncdir));
}
// Store the product name for all target types.
buildSettings->AddAttribute("PRODUCT_NAME", this->CreateString(realName));
- buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir));
// Handle settings for each target type.
switch (gtgt->GetType()) {
@@ -2681,10 +2725,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
BuildObjectListOrString sysfdirs(this, true);
const bool emitSystemIncludes = this->XcodeVersion >= 83;
+ // Choose a language to use for target-wide include directories.
+ std::string const& langForIncludes = llang;
std::vector<std::string> includes;
- if (!langForPreprocessor.empty()) {
+ if (!langForIncludes.empty()) {
this->CurrentLocalGenerator->GetIncludeDirectories(
- includes, gtgt, langForPreprocessor, configName);
+ includes, gtgt, langForIncludes, configName);
}
std::set<std::string> emitted;
emitted.insert("/System/Library/Frameworks");
@@ -2697,7 +2743,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string incpath = this->XCodeEscapePath(frameworkDir);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(include, configName,
- langForPreprocessor)) {
+ langForIncludes)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -2707,7 +2753,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string incpath = this->XCodeEscapePath(include);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(include, configName,
- langForPreprocessor)) {
+ langForIncludes)) {
sysdirs.Add(incpath);
} else {
dirs.Add(incpath);
@@ -2721,7 +2767,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string incpath = this->XCodeEscapePath(fwDir);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(fwDir, configName,
- langForPreprocessor)) {
+ langForIncludes)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -2734,6 +2780,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
}
if (!dirs.IsEmpty()) {
buildSettings->AddAttribute("HEADER_SEARCH_PATHS", dirs.CreateList());
+ if (languages.count("Swift")) {
+ buildSettings->AddAttribute("SWIFT_INCLUDE_PATHS", dirs.CreateList());
+ }
}
if (!sysfdirs.IsEmpty()) {
buildSettings->AddAttribute("SYSTEM_FRAMEWORK_SEARCH_PATHS",
@@ -3618,9 +3667,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
linkDir = libItem->Value.Value;
}
if (cmHasSuffix(libItem->GetFeatureName(), "FRAMEWORK"_s)) {
- auto fwItems = this->SplitFrameworkPath(linkDir, true);
- if (fwItems && !fwItems->first.empty()) {
- linkDir = std::move(fwItems->first);
+ auto fwDescriptor = this->SplitFrameworkPath(
+ linkDir, cmGlobalGenerator::FrameworkFormat::Extended);
+ if (fwDescriptor && !fwDescriptor->Directory.empty()) {
+ linkDir = fwDescriptor->Directory;
if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(),
linkDir) == frameworkSearchPaths.end()) {
frameworkSearchPaths.push_back(linkDir);
@@ -3753,14 +3803,20 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
// add the library search paths
{
BuildObjectListOrString libSearchPaths(this, true);
+
std::string linkDirs;
for (auto const& libDir : cli->GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
- libSearchPaths.Add(this->XCodeEscapePath(
- libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"));
+ cmPolicies::PolicyStatus cmp0142 =
+ target->GetTarget()->GetPolicyStatusCMP0142();
+ if (cmp0142 == cmPolicies::OLD || cmp0142 == cmPolicies::WARN) {
+ libSearchPaths.Add(this->XCodeEscapePath(
+ libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"));
+ }
libSearchPaths.Add(this->XCodeEscapePath(libDir));
}
}
+
// Add previously collected paths where to look for libraries
// that were added to "Link Binary With Libraries"
for (auto& libDir : linkSearchPaths) {
@@ -3800,6 +3856,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
const auto& fwPaths = cli->GetFrameworkPaths();
emitted.insert(fwPaths.begin(), fwPaths.end());
BuildObjectListOrString libPaths(this, true);
+ BuildObjectListOrString fwSearchPaths(this, true);
for (auto const& libItem : configItemMap[configName]) {
auto const& libName = *libItem;
if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
@@ -3810,13 +3867,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
bool isFramework =
cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s);
if (isFramework) {
- const auto fwItems =
- this->SplitFrameworkPath(cleanPath, isFramework);
- if (!fwItems->first.empty() &&
- emitted.insert(fwItems->first).second) {
+ const auto fwDescriptor = this->SplitFrameworkPath(
+ cleanPath, cmGlobalGenerator::FrameworkFormat::Extended);
+ if (!fwDescriptor->Directory.empty() &&
+ emitted.insert(fwDescriptor->Directory).second) {
// This is a search path we had not added before and it isn't
// an implicit search path, so we need it
- libPaths.Add("-F " + this->XCodeEscapePath(fwItems->first));
+ fwSearchPaths.Add(
+ this->XCodeEscapePath(fwDescriptor->Directory));
}
if (libName.GetFeatureName() == "__CMAKE_LINK_FRAMEWORK"_s) {
// use the full path
@@ -3824,10 +3882,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
libName.GetFormattedItem(this->XCodeEscapePath(cleanPath))
.Value);
} else {
- libPaths.Add(
- libName
- .GetFormattedItem(this->XCodeEscapePath(fwItems->second))
- .Value);
+ libPaths.Add(libName
+ .GetFormattedItem(this->XCodeEscapePath(
+ fwDescriptor->GetLinkName()))
+ .Value);
}
} else {
libPaths.Add(
@@ -3855,9 +3913,16 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
target->AddDependTarget(configName, libName.Target->GetName());
}
}
- this->AppendBuildSettingAttribute(target,
- this->GetTargetLinkFlagsVar(gt),
- libPaths.CreateList(), configName);
+ if (!libPaths.IsEmpty()) {
+ this->AppendBuildSettingAttribute(target,
+ this->GetTargetLinkFlagsVar(gt),
+ libPaths.CreateList(), configName);
+ }
+ if (!fwSearchPaths.IsEmpty()) {
+ this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
+ fwSearchPaths.CreateList(),
+ configName);
+ }
}
}
}
@@ -4339,7 +4404,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateString(swiftVersion));
}
- std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build");
+ std::string const symroot = this->GetSymrootDir();
buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot));
// Inside a try_compile project, do not require signing on any platform.
@@ -4438,14 +4503,17 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
return true;
}
-std::string cmGlobalXCodeGenerator::GetObjectsDirectory(
- const std::string& projName, const std::string& configName,
- const cmGeneratorTarget* t, const std::string& variant) const
+std::string cmGlobalXCodeGenerator::GetSymrootDir() const
{
- std::string dir = cmStrCat(
- t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName,
- ".build/", configName, '/', t->GetName(), ".build/", variant);
- return dir;
+ return cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/build");
+}
+
+std::string cmGlobalXCodeGenerator::GetTargetTempDir(
+ cmGeneratorTarget const* gt, std::string const& configName) const
+{
+ // Use a path inside the SYMROOT.
+ return cmStrCat(this->GetSymrootDir(), '/', gt->GetName(), ".build/",
+ configName);
}
void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
@@ -4571,10 +4639,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackMakefile(
for (auto objLib : objlibs) {
const std::string objLibName = objLib->GetName();
- std::string d = cmStrCat(
- this->GetObjectsDirectory(this->CurrentProject, configName, objLib,
- OBJECT_LIBRARY_ARTIFACT_DIR),
- "lib", objLibName, ".a");
+ std::string d = cmStrCat(this->GetTargetTempDir(gt, configName),
+ "/lib", objLibName, ".a");
std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
@@ -4588,8 +4654,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackMakefile(
// if building for more than one architecture
// then remove those executables as well
if (this->Architectures.size() > 1) {
- std::string universal = this->GetObjectsDirectory(
- this->CurrentProject, configName, gt, "$(OBJDIR)/");
+ std::string universal =
+ cmStrCat(this->GetTargetTempDir(gt, configName), "/$(OBJDIR)/");
for (const auto& architecture : this->Architectures) {
std::string universalFile = cmStrCat(universal, architecture, '/',
gt->GetFullName(configName));
@@ -4986,14 +5052,10 @@ bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
- std::string configName = this->GetCMakeCFGIntDir();
auto objectDirArch = GetTargetObjectDirArch(*gt, this->ObjectDirArch);
-
- std::string dir =
- cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt,
- "$(OBJECT_FILE_DIR_normal:base)/"),
- objectDirArch, '/');
- gt->ObjectDirectory = dir;
+ gt->ObjectDirectory =
+ cmStrCat(this->GetTargetTempDir(gt, this->GetCMakeCFGIntDir()),
+ "/$(OBJECT_FILE_DIR_normal:base)/", objectDirArch, '/');
}
std::string cmGlobalXCodeGenerator::GetDeploymentPlatform(const cmMakefile* mf)
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 92e45280d..9ae75fb1d 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -339,10 +339,9 @@ private:
std::string GetLibraryOrFrameworkPath(const std::string& path) const;
- std::string GetObjectsDirectory(const std::string& projName,
- const std::string& configName,
- const cmGeneratorTarget* t,
- const std::string& variant) const;
+ std::string GetSymrootDir() const;
+ std::string GetTargetTempDir(cmGeneratorTarget const* gt,
+ std::string const& configName) const;
static std::string GetDeploymentPlatform(const cmMakefile* mf);
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 0da72b15d..c2a09c108 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -150,7 +150,7 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus status(mf);
mf.ExecuteCommand(func, status);
if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
+ inStatus.SetReturnInvoked(status.GetReturnVariables());
return true;
}
if (status.GetBreakInvoked()) {
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 7ca5b2318..82adca83c 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -12,18 +12,22 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmsys/Glob.hxx"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
+#include "cmExperimental.h"
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCommandArguments.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -54,13 +58,13 @@ namespace {
struct RuntimeDependenciesArgs
{
- std::vector<std::string> Directories;
- std::vector<std::string> PreIncludeRegexes;
- std::vector<std::string> PreExcludeRegexes;
- std::vector<std::string> PostIncludeRegexes;
- std::vector<std::string> PostExcludeRegexes;
- std::vector<std::string> PostIncludeFiles;
- std::vector<std::string> PostExcludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles;
};
auto const RuntimeDependenciesArgHelper =
@@ -109,6 +113,8 @@ public:
const cmInstallCommandArguments* args) const;
std::string GetLibraryDestination(
const cmInstallCommandArguments* args) const;
+ std::string GetCxxModulesBmiDestination(
+ const cmInstallCommandArguments* args) const;
std::string GetIncludeDestination(
const cmInstallCommandArguments* args) const;
std::string GetSysconfDestination(
@@ -401,16 +407,17 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Archive;
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Object;
- std::vector<std::string> Framework;
- std::vector<std::string> Bundle;
- std::vector<std::string> Includes;
- std::vector<std::string> PrivateHeader;
- std::vector<std::string> PublicHeader;
- std::vector<std::string> Resource;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Archive;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Object;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Includes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PrivateHeader;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PublicHeader;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Resource;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> CxxModulesBmi;
std::vector<std::vector<std::string>> FileSets;
};
@@ -426,7 +433,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
.Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
.Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
.Bind("RESOURCE"_s, &ArgVectors::Resource)
- .Bind("FILE_SET"_s, &ArgVectors::FileSets);
+ .Bind("FILE_SET"_s, &ArgVectors::FileSets)
+ .Bind("CXX_MODULES_BMI"_s, &ArgVectors::CxxModulesBmi);
std::vector<std::string> genericArgVector;
ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
@@ -434,26 +442,25 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// now parse the generic args (i.e. the ones not specialized on LIBRARY/
// ARCHIVE, RUNTIME etc. (see above)
// These generic args also contain the targets and the export stuff
- std::vector<std::string> targetList;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList;
std::string exports;
- std::vector<std::string> runtimeDependenciesArgVector;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>>
+ runtimeDependenciesArgVector;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
- std::vector<std::string> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("TARGETS"_s, targetList);
genericArgs.Bind("EXPORT"_s, exports);
genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
- genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
- bool withRuntimeDependencies =
- std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
- parsedArgs.end();
RuntimeDependenciesArgs runtimeDependenciesArgs =
- RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
- &unknownArgs);
+ runtimeDependenciesArgVector
+ ? RuntimeDependenciesArgHelper.Parse(*runtimeDependenciesArgVector,
+ &unknownArgs)
+ : RuntimeDependenciesArgs();
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
@@ -467,6 +474,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
cmInstallCommandIncludesArgument includesArgs;
std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
argVectors.FileSets.size(), { helper.DefaultComponentName });
+ cmInstallCommandArguments cxxModuleBmiArgs(helper.DefaultComponentName);
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -490,6 +498,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
fileSetArgs[i] = std::move(fileSetArg);
}
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+ if (!supportCxx20FileSetTypes) {
+ std::copy(argVectors.CxxModulesBmi.begin(), argVectors.CxxModulesBmi.end(),
+ std::back_inserter(unknownArgs));
+ } else {
+ cxxModuleBmiArgs.Parse(argVectors.CxxModulesBmi, &unknownArgs);
+ }
+
if (!unknownArgs.empty()) {
// Unknown argument.
status.SetError(
@@ -510,6 +527,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& fileSetArg : fileSetArgs) {
fileSetArg.SetGenericArguments(&genericArgs);
}
+ cxxModuleBmiArgs.SetGenericArguments(&genericArgs);
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
@@ -523,6 +541,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& fileSetArg : fileSetArgs) {
success = success && fileSetArg.Finalize();
}
+ if (supportCxx20FileSetTypes) {
+ success = success && cxxModuleBmiArgs.Finalize();
+ }
if (!success) {
return false;
@@ -536,7 +557,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.GetNamelinkOnly(); })) {
+ -> bool { return fileSetArg.GetNamelinkOnly(); }) ||
+ cxxModuleBmiArgs.GetNamelinkOnly()) {
status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
@@ -548,7 +570,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.GetNamelinkSkip(); })) {
+ -> bool { return fileSetArg.GetNamelinkSkip(); }) ||
+ cxxModuleBmiArgs.GetNamelinkSkip()) {
status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
@@ -564,7 +587,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
resourceArgs.HasNamelinkComponent() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.HasNamelinkComponent(); })) {
+ -> bool { return fileSetArg.HasNamelinkComponent(); }) ||
+ cxxModuleBmiArgs.HasNamelinkComponent()) {
status.SetError(
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
"The NAMELINK_COMPONENT option may be specified only following "
@@ -583,7 +607,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
!publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return !fileSetArg.GetType().empty(); })) {
+ -> bool { return !fileSetArg.GetType().empty(); }) ||
+ !cxxModuleBmiArgs.GetType().empty()) {
status.SetError(
"TARGETS given TYPE option. The TYPE option may only be specified in "
" install(FILES) and install(DIRECTORIES).");
@@ -597,7 +622,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
- if (withRuntimeDependencies) {
+ if (runtimeDependenciesArgVector) {
if (!runtimeDependencySetArg.empty()) {
status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
"RUNTIME_DEPENDENCY_SET.");
@@ -706,6 +731,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bool installsPublicHeader = false;
bool installsResource = false;
std::vector<bool> installsFileSet(fileSetArgs.size(), false);
+ bool installsCxxModuleBmi = false;
// Generate install script code to install the given targets.
for (cmTarget* ti : targets) {
@@ -722,6 +748,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators;
+ std::unique_ptr<cmInstallCxxModuleBmiGenerator> cxxModuleBmiGenerator;
// Avoid selecting default destinations for PUBLIC_HEADER and
// PRIVATE_HEADER if any artifacts are specified.
@@ -760,6 +787,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto const& gen : fileSetGenerators) {
te->FileSetGenerators[gen->GetFileSet()] = gen.get();
}
+ te->CxxModuleBmiGenerator = cxxModuleBmiGenerator.get();
target.AddInstallIncludeDirectories(
*te, cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
@@ -1105,6 +1133,19 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
}
+ if (supportCxx20FileSetTypes &&
+ !cxxModuleBmiArgs.GetDestination().empty()) {
+ cxxModuleBmiGenerator = cm::make_unique<cmInstallCxxModuleBmiGenerator>(
+ target.GetName(),
+ helper.GetCxxModulesBmiDestination(&cxxModuleBmiArgs),
+ cxxModuleBmiArgs.GetPermissions(),
+ cxxModuleBmiArgs.GetConfigurations(), cxxModuleBmiArgs.GetComponent(),
+ cmInstallGenerator::SelectMessageLevel(target.GetMakefile()),
+ cxxModuleBmiArgs.GetExcludeFromAll(), cxxModuleBmiArgs.GetOptional(),
+ helper.Makefile->GetBacktrace());
+ target.SetHaveInstallRule(true);
+ }
+
// Add this install rule to an export if one was specified.
if (!addTargetExport()) {
return false;
@@ -1121,6 +1162,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator;
installsPublicHeader = installsPublicHeader || publicHeaderGenerator;
installsResource = installsResource || resourceGenerator;
+ installsCxxModuleBmi = installsCxxModuleBmi || cxxModuleBmiGenerator;
helper.Makefile->AddInstallGenerator(std::move(archiveGenerator));
helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
@@ -1135,9 +1177,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& gen : fileSetGenerators) {
helper.Makefile->AddInstallGenerator(std::move(gen));
}
+ helper.Makefile->AddInstallGenerator(std::move(cxxModuleBmiGenerator));
}
- if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
+ if (runtimeDependenciesArgVector && !runtimeDependencySet->Empty()) {
AddInstallRuntimeDependenciesGenerator(
helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
@@ -1192,6 +1235,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
fileSetArgs[i].GetComponent());
}
}
+ if (installsCxxModuleBmi) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ cxxModuleBmiArgs.GetComponent());
+ }
return true;
}
@@ -1206,10 +1253,10 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Framework;
- std::vector<std::string> Bundle;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle;
};
static auto const argHelper = cmArgumentParser<ArgVectors>{}
@@ -1223,7 +1270,7 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
// now parse the generic args (i.e. the ones not specialized on LIBRARY,
// RUNTIME etc. (see above)
- std::vector<std::string> targetList;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
@@ -1464,7 +1511,7 @@ bool HandleFilesMode(std::vector<std::string> const& args,
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
cmInstallCommandArguments ica(helper.DefaultComponentName);
- std::vector<std::string> files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> files;
ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs);
@@ -1950,7 +1997,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
+ ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true,
helper.Makefile->GetBacktrace()));
return true;
@@ -1973,12 +2020,19 @@ bool HandleExportMode(std::vector<std::string> const& args,
std::string name_space;
bool exportOld = false;
std::string filename;
+ std::string cxx_modules_directory;
ica.Bind("EXPORT"_s, exp);
ica.Bind("NAMESPACE"_s, name_space);
ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
ica.Bind("FILE"_s, filename);
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+ if (supportCxx20FileSetTypes) {
+ ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory);
+ }
+
std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs);
@@ -2064,8 +2118,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
- helper.Makefile->GetBacktrace()));
+ ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
+ exportOld, false, helper.Makefile->GetBacktrace()));
return true;
}
@@ -2088,9 +2142,9 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
};
static auto const argHelper = cmArgumentParser<ArgVectors>{}
@@ -2106,11 +2160,9 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
// These generic args also contain the runtime dependency set
std::string runtimeDependencySetArg;
std::vector<std::string> runtimeDependencyArgVector;
- std::vector<std::string> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
- genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
- &parsedArgs);
+ genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector);
bool success = genericArgs.Finalize();
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
@@ -2280,6 +2332,15 @@ std::string Helper::GetLibraryDestination(
return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
}
+std::string Helper::GetCxxModulesBmiDestination(
+ const cmInstallCommandArguments* args) const
+{
+ if (args) {
+ return args->GetDestination();
+ }
+ return {};
+}
+
std::string Helper::GetIncludeDestination(
const cmInstallCommandArguments* args) const
{
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 79bd945c7..6e46aaca5 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
class cmInstallCommandArguments : public cmArgumentParser<void>
{
@@ -44,8 +45,8 @@ private:
std::string NamelinkComponent;
bool ExcludeFromAll = false;
std::string Rename;
- std::vector<std::string> Permissions;
- std::vector<std::string> Configurations;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Permissions;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Configurations;
bool Optional = false;
bool NamelinkOnly = false;
bool NamelinkSkip = false;
diff --git a/Source/cmInstallCxxModuleBmiGenerator.cxx b/Source/cmInstallCxxModuleBmiGenerator.cxx
new file mode 100644
index 000000000..1ef1eaa8f
--- /dev/null
+++ b/Source/cmInstallCxxModuleBmiGenerator.cxx
@@ -0,0 +1,75 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallCxxModuleBmiGenerator.h"
+
+#include <ostream>
+#include <utility>
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
+
+cmInstallCxxModuleBmiGenerator::cmInstallCxxModuleBmiGenerator(
+ std::string target, std::string const& dest, std::string file_permissions,
+ std::vector<std::string> const& configurations, std::string const& component,
+ MessageLevel message, bool exclude_from_all, bool optional,
+ cmListFileBacktrace backtrace)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all, false, std::move(backtrace))
+ , TargetName(std::move(target))
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+cmInstallCxxModuleBmiGenerator::~cmInstallCxxModuleBmiGenerator() = default;
+
+bool cmInstallCxxModuleBmiGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+
+ this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallCxxModuleBmiGenerator::GetScriptLocation(
+ std::string const& config) const
+{
+ char const* config_name = config.c_str();
+ if (config.empty()) {
+ config_name = "noconfig";
+ }
+ return cmStrCat(this->Target->GetSupportDirectory(),
+ "/install-cxx-module-bmi-", config_name, ".cmake");
+}
+
+std::string cmInstallCxxModuleBmiGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
+}
+
+void cmInstallCxxModuleBmiGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ auto const& loc = this->GetScriptLocation(config);
+ if (loc.empty()) {
+ return;
+ }
+ os << indent << "include(\""
+ << cmOutputConverter::EscapeForCMake(
+ loc, cmOutputConverter::WrapQuotes::NoWrap)
+ << "\" OPTIONAL)\n";
+}
diff --git a/Source/cmInstallCxxModuleBmiGenerator.h b/Source/cmInstallCxxModuleBmiGenerator.h
new file mode 100644
index 000000000..21edb2ef2
--- /dev/null
+++ b/Source/cmInstallCxxModuleBmiGenerator.h
@@ -0,0 +1,52 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmListFileBacktrace;
+class cmLocalGenerator;
+
+/** \class cmInstallCxxModuleBmiGenerator
+ * \brief Generate C++ module BMI installation rules.
+ */
+class cmInstallCxxModuleBmiGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallCxxModuleBmiGenerator(
+ std::string target, std::string const& dest, std::string file_permissions,
+ std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message, bool exclude_from_all,
+ bool optional, cmListFileBacktrace backtrace);
+ ~cmInstallCxxModuleBmiGenerator() override;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ std::string const& GetFilePermissions() const
+ {
+ return this->FilePermissions;
+ }
+ std::string GetDestination(std::string const& config) const;
+ std::string GetScriptLocation(std::string const& config) const;
+ cmGeneratorTarget const* GetTarget() const { return this->Target; }
+ bool GetOptional() const { return this->Optional; }
+ MessageLevel GetMessageLevel() const { return this->Message; }
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+ std::string const TargetName;
+ cmGeneratorTarget const* Target = nullptr;
+ cmLocalGenerator* LocalGenerator = nullptr;
+ std::string const FilePermissions;
+ bool const Optional;
+};
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index b80437dae..1d81b0ba7 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -23,7 +23,8 @@ cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, std::string const& destination,
std::string file_permissions, std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message, bool exclude_from_all,
- std::string filename, std::string name_space, bool exportOld, bool android,
+ std::string filename, std::string name_space,
+ std::string cxx_modules_directory, bool exportOld, bool android,
cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
exclude_from_all, false, std::move(backtrace))
@@ -31,6 +32,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
, FilePermissions(std::move(file_permissions))
, FileName(std::move(filename))
, Namespace(std::move(name_space))
+ , CxxModulesDirectory(std::move(cxx_modules_directory))
, ExportOld(exportOld)
{
if (android) {
@@ -141,6 +143,75 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
os << indent << "endif()\n";
files.clear();
}
+
+ // Now create a configuration-specific install rule for the C++ module import
+ // property file of each configuration.
+ auto cxx_module_dest =
+ cmStrCat(this->Destination, '/', this->CxxModulesDirectory);
+ std::string config_file_example;
+ for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
+ config_file_example = i.second;
+ break;
+ }
+ if (!config_file_example.empty()) {
+ // Remove old per-configuration export files if the main changes.
+ std::string installedDir = cmStrCat(
+ "$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/');
+ std::string installedFile = cmStrCat(installedDir, "/cxx-modules.cmake");
+ std::string toInstallFile =
+ cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
+ "/cxx-modules.cmake");
+ os << indent << "if(EXISTS \"" << installedFile << "\")\n";
+ Indent indentN = indent.Next();
+ Indent indentNN = indentN.Next();
+ Indent indentNNN = indentNN.Next();
+ /* clang-format off */
+ os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
+ << indentN << " \"" << installedFile << "\"\n"
+ << indentN << " \"" << toInstallFile << "\")\n";
+ os << indentN << "if(_cmake_export_file_changed)\n";
+ os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
+ << this->EFGen->GetConfigImportFileGlob() << "\")\n";
+ os << indentNN << "if(_cmake_old_config_files)\n";
+ os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n";
+ os << indentNNN << R"(message(STATUS "Old C++ module export file \")" << installedFile
+ << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n";
+ os << indentNNN << "unset(_cmake_old_config_files_text)\n";
+ os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n";
+ os << indentNN << "endif()\n";
+ os << indentNN << "unset(_cmake_old_config_files)\n";
+ os << indentN << "endif()\n";
+ os << indentN << "unset(_cmake_export_file_changed)\n";
+ os << indent << "endif()\n";
+ /* clang-format on */
+
+ // All of these files are siblings; get its location to know where the
+ // "anchor" file is.
+ files.push_back(toInstallFile);
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent);
+ files.clear();
+ }
+ for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
+ files.push_back(i.second);
+ std::string config_test = this->CreateConfigTest(i.first);
+ os << indent << "if(" << config_test << ")\n";
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent.Next());
+ os << indent << "endif()\n";
+ files.clear();
+ }
+ for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) {
+ std::string config_test = this->CreateConfigTest(i.first);
+ os << indent << "if(" << config_test << ")\n";
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent.Next());
+ os << indent << "endif()\n";
+ files.clear();
+ }
}
void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 02fe1fa21..346ca67a8 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -28,7 +28,8 @@ public:
const std::vector<std::string>& configurations,
std::string const& component, MessageLevel message,
bool exclude_from_all, std::string filename,
- std::string name_space, bool exportOld,
+ std::string name_space,
+ std::string cxx_modules_directory, bool exportOld,
bool android, cmListFileBacktrace backtrace);
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
~cmInstallExportGenerator() override;
@@ -50,6 +51,10 @@ public:
std::string GetDestinationFile() const;
std::string GetFileName() const { return this->FileName; }
std::string GetTempDir() const;
+ std::string GetCxxModuleDirectory() const
+ {
+ return this->CxxModulesDirectory;
+ }
protected:
void GenerateScript(std::ostream& os) override;
@@ -64,6 +69,7 @@ protected:
std::string const FilePermissions;
std::string const FileName;
std::string const Namespace;
+ std::string const CxxModulesDirectory;
bool const ExportOld;
cmLocalGenerator* LocalGenerator = nullptr;
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 43f1b8e6d..b06dc3dd1 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -57,7 +57,6 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
// For this we only consider targets
using ItemVector = cmComputeLinkInformation::ItemVector;
ItemVector const& items = cli.GetItems();
- std::string config = cli.GetConfig();
return std::any_of(
items.begin(), items.end(),
[](cmComputeLinkInformation::Item const& item) -> bool {
@@ -69,6 +68,26 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
});
}
+bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinkingIPOFlag(
+ cmComputeLinkInformation& cli)
+{
+ // Determine if this item might requires device linking.
+ // For this we only consider targets
+ using ItemVector = cmComputeLinkInformation::ItemVector;
+ ItemVector const& items = cli.GetItems();
+ std::string config = cli.GetConfig();
+ return std::any_of(
+ items.begin(), items.end(),
+ [config](cmComputeLinkInformation::Item const& item) -> bool {
+ return item.Target &&
+ item.Target->GetType() == cmStateEnums::STATIC_LIBRARY &&
+ // this dependency requires us to device link it
+ !item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS") &&
+ item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION") &&
+ item.Target->IsIPOEnabled("CUDA", config);
+ });
+}
+
void cmLinkLineDeviceComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString,
std::vector<BT<std::string>>& linkLibraries)
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index dee625b68..091630729 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -30,6 +30,7 @@ public:
delete;
bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli);
+ bool ComputeRequiresDeviceLinkingIPOFlag(cmComputeLinkInformation& cli);
void ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString,
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 91157cbf0..6270c825f 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -347,6 +347,7 @@ enum class NestingStateEnum
Foreach,
Function,
Macro,
+ Block
};
struct NestingState
@@ -434,6 +435,16 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const
return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
+ } else if (name == "block") {
+ stack.push_back({
+ NestingStateEnum::Block,
+ cmListFileContext::FromListFileFunction(func, this->FileName),
+ });
+ } else if (name == "endblock") {
+ if (!TopIs(stack, NestingStateEnum::Block)) {
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
+ }
+ stack.pop_back();
}
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 99bd05fdb..b2b724a8a 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -15,6 +15,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -36,6 +37,7 @@
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
@@ -1385,7 +1387,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags(
}
void cmLocalGenerator::GetDeviceLinkFlags(
- cmLinkLineComputer& linkLineComputer, const std::string& config,
+ cmLinkLineDeviceComputer& linkLineComputer, const std::string& config,
std::string& linkLibs, std::string& linkFlags, std::string& frameworkPath,
std::string& linkPath, cmGeneratorTarget* target)
{
@@ -1393,6 +1395,18 @@ void cmLocalGenerator::GetDeviceLinkFlags(
cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
+ auto linklang = linkLineComputer.GetLinkerLanguage(target, config);
+ auto ipoEnabled = target->IsIPOEnabled(linklang, config);
+ if (!ipoEnabled) {
+ ipoEnabled = linkLineComputer.ComputeRequiresDeviceLinkingIPOFlag(*pcli);
+ }
+ if (ipoEnabled) {
+ if (cmValue cudaIPOFlags = this->Makefile->GetDefinition(
+ "CMAKE_CUDA_DEVICE_LINK_OPTIONS_IPO")) {
+ linkFlags += cudaIPOFlags;
+ }
+ }
+
if (pcli) {
// Compute the required device link libraries when
// resolving gpu lang device symbols
@@ -1400,6 +1414,8 @@ void cmLocalGenerator::GetDeviceLinkFlags(
linkPath);
}
+ // iterate link deps and see if any of them need IPO
+
std::vector<std::string> linkOpts;
target->GetLinkOptions(linkOpts, config, "CUDA");
// LINK_OPTIONS are escaped.
@@ -1594,7 +1610,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags(
cmMakefile* mf = this->GetMakefile();
// Add language-specific flags.
- this->AddLanguageFlags(compileFlags, target, lang, config);
+ this->AddLanguageFlags(compileFlags, target, cmBuildStep::Compile, lang,
+ config);
if (target->IsIPOEnabled(lang, config)) {
this->AppendFeatureOptions(compileFlags, lang, "IPO");
@@ -1907,6 +1924,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
void cmLocalGenerator::AddLanguageFlags(std::string& flags,
cmGeneratorTarget const* target,
+ cmBuildStep compileOrLink,
const std::string& lang,
const std::string& config)
{
@@ -1930,7 +1948,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
}
} else if (lang == "CUDA") {
- target->AddCUDAArchitectureFlags(flags);
+ target->AddCUDAArchitectureFlags(compileOrLink, config, flags);
target->AddCUDAToolkitFlags(flags);
} else if (lang == "ISPC") {
target->AddISPCTargetFlags(flags);
@@ -2027,6 +2045,31 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
}
}
+
+ // Add MSVC debug information format flags if CMP0141 is NEW.
+ if (cm::optional<std::string> msvcDebugInformationFormat =
+ this->GetMSVCDebugFormatName(config, target)) {
+ if (!msvcDebugInformationFormat->empty()) {
+ if (cmValue msvcDebugInformationFormatOptions =
+ this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang,
+ "_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_",
+ *msvcDebugInformationFormat))) {
+ this->AppendCompileOptions(flags, *msvcDebugInformationFormatOptions);
+ } else if ((this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_ID")) == "MSVC"_s ||
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_SIMULATE_ID")) == "MSVC"_s) &&
+ !cmSystemTools::GetErrorOccurredFlag()) {
+ // The compiler uses the MSVC ABI so it needs a known runtime library.
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("MSVC_DEBUG_INFORMATION_FORMAT value '",
+ *msvcDebugInformationFormat,
+ "' not known for this ", lang,
+ " compiler."));
+ }
+ }
+ }
}
void cmLocalGenerator::AddLanguageFlagsForLinking(
@@ -2042,7 +2085,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
this->AddCompilerRequirementFlag(flags, target, lang, config);
}
- this->AddLanguageFlags(flags, target, lang, config);
+ this->AddLanguageFlags(flags, target, cmBuildStep::Link, lang, config);
if (target->IsIPOEnabled(lang, config)) {
this->AppendFeatureOptions(flags, lang, "IPO");
@@ -2578,7 +2621,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
if (pchSource.empty() || pchHeader.empty()) {
if (this->GetGlobalGenerator()->IsXcode() && !pchLangSet.empty()) {
for (auto* sf : sources) {
- if (pchLangSet.find(sf->GetLanguage()) == pchLangSet.end()) {
+ const auto sourceLanguage = sf->GetLanguage();
+ if (!sourceLanguage.empty() &&
+ pchLangSet.find(sourceLanguage) == pchLangSet.end()) {
sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
}
}
@@ -2630,13 +2675,24 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_FLAGS_", configUpper));
- bool editAndContinueDebugInfo =
- langFlags.find("/ZI") != std::string::npos ||
- langFlags.find("-ZI") != std::string::npos;
-
- bool enableDebuggingInformation =
- langFlags.find("/Zi") != std::string::npos ||
- langFlags.find("-Zi") != std::string::npos;
+ bool editAndContinueDebugInfo = false;
+ bool programDatabaseDebugInfo = false;
+ cm::optional<std::string> msvcDebugInformationFormat =
+ this->GetMSVCDebugFormatName(config, target);
+ if (msvcDebugInformationFormat &&
+ !msvcDebugInformationFormat->empty()) {
+ editAndContinueDebugInfo =
+ *msvcDebugInformationFormat == "EditAndContinue";
+ programDatabaseDebugInfo =
+ *msvcDebugInformationFormat == "ProgramDatabase";
+ } else {
+ editAndContinueDebugInfo =
+ langFlags.find("/ZI") != std::string::npos ||
+ langFlags.find("-ZI") != std::string::npos;
+ programDatabaseDebugInfo =
+ langFlags.find("/Zi") != std::string::npos ||
+ langFlags.find("-Zi") != std::string::npos;
+ }
// MSVC 2008 is producing both .pdb and .idb files with /Zi.
bool msvc2008OrLess =
@@ -2652,7 +2708,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
if (editAndContinueDebugInfo || msvc2008OrLess) {
this->CopyPchCompilePdb(config, target, *ReuseFrom,
reuseTarget, { ".pdb", ".idb" });
- } else if (enableDebuggingInformation) {
+ } else if (programDatabaseDebugInfo) {
this->CopyPchCompilePdb(config, target, *ReuseFrom,
reuseTarget, { ".pdb" });
}
@@ -2671,7 +2727,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
cmStrCat(linkerProperty, configUpper),
cmStrCat(" ",
this->ConvertToOutputFormat(pchSourceObj, SHELL)),
- true);
+ cm::nullopt, true);
} else if (reuseTarget->GetType() ==
cmStateEnums::OBJECT_LIBRARY) {
// FIXME: This can propagate more than one level, unlike
@@ -2816,6 +2872,26 @@ void cmLocalGenerator::CopyPchCompilePdb(
target_compile_pdb_dir);
}
+cm::optional<std::string> cmLocalGenerator::GetMSVCDebugFormatName(
+ std::string const& config, cmGeneratorTarget const* target)
+{
+ // MSVC debug information format selection is activated by the presence
+ // of a default whether or not it is overridden by a property.
+ cm::optional<std::string> msvcDebugInformationFormat;
+ cmValue msvcDebugInformationFormatDefault = this->Makefile->GetDefinition(
+ "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT");
+ if (cmNonempty(msvcDebugInformationFormatDefault)) {
+ cmValue msvcDebugInformationFormatValue =
+ target->GetProperty("MSVC_DEBUG_INFORMATION_FORMAT");
+ if (!msvcDebugInformationFormatValue) {
+ msvcDebugInformationFormatValue = msvcDebugInformationFormatDefault;
+ }
+ msvcDebugInformationFormat = cmGeneratorExpression::Evaluate(
+ *msvcDebugInformationFormatValue, this, config, target);
+ }
+ return msvcDebugInformationFormat;
+}
+
namespace {
inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 7cae1fc87..765441cb1 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -35,6 +35,7 @@ class cmGeneratorTarget;
class cmGlobalGenerator;
class cmImplicitDependsList;
class cmLinkLineComputer;
+class cmLinkLineDeviceComputer;
class cmMakefile;
class cmRulePlaceholderExpander;
class cmSourceFile;
@@ -59,6 +60,13 @@ enum class cmDependencyScannerKind
Compiler
};
+/** What to compute language flags for */
+enum class cmBuildStep
+{
+ Compile,
+ Link
+};
+
/** Target and source file which have a specific output. */
struct cmSourcesWithOutput
{
@@ -143,7 +151,8 @@ public:
const std::string& filterArch = std::string());
void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target,
- const std::string& lang, const std::string& config);
+ cmBuildStep compileOrLink, const std::string& lang,
+ const std::string& config);
void AddLanguageFlagsForLinking(std::string& flags,
cmGeneratorTarget const* target,
const std::string& lang,
@@ -476,7 +485,7 @@ public:
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
- void GetDeviceLinkFlags(cmLinkLineComputer& linkLineComputer,
+ void GetDeviceLinkFlags(cmLinkLineDeviceComputer& linkLineComputer,
const std::string& config, std::string& linkLibs,
std::string& linkFlags, std::string& frameworkPath,
std::string& linkPath, cmGeneratorTarget* target);
@@ -637,6 +646,10 @@ private:
cmGeneratorTarget* reuseTarget,
std::vector<std::string> const& extensions);
+ // Returns MSVC_DEBUG_INFORMATION_FORMAT value if CMP0141 is NEW.
+ cm::optional<std::string> GetMSVCDebugFormatName(
+ std::string const& config, cmGeneratorTarget const* target);
+
struct UnityBatchedSource
{
cmSourceFile* Source = nullptr;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 106f76bf8..c11f5b413 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -88,27 +88,11 @@ void cmLocalNinjaGenerator::Generate()
cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(),
"localized /showIncludes string");
this->GetRulesFileStream() << "msvc_deps_prefix = ";
-#ifdef _WIN32
- // Ninja uses the ANSI Windows APIs, so strings in the rules file
- // typically need to be ANSI encoded. However, in this case the compiler
- // is being invoked using the UTF-8 codepage so the /showIncludes prefix
- // will be UTF-8 encoded on stdout. Ninja can't successfully compare this
- // UTF-8 encoded prefix to the ANSI encoded msvc_deps_prefix if it
- // contains any non-ASCII characters and dependency checking will fail.
- // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though
- // the rest of the file is ANSI encoded.
- if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8 &&
- this->GetGlobalGenerator()->GetMakefileEncoding() != codecvt::None) {
- this->GetRulesFileStream().WriteRaw(showIncludesPrefix);
- } else {
- // Ninja 1.11 and above uses the UTF-8 code page if it's supported, so
- // in that case we can write it normally without using raw bytes.
- this->GetRulesFileStream() << showIncludesPrefix;
- }
-#else
- // It's safe to use the standard encoding on other platforms.
- this->GetRulesFileStream() << showIncludesPrefix;
-#endif
+ // 'cl /showIncludes' encodes output in the console output code page.
+ // It may differ from the encoding used for file paths in 'build.ninja'.
+ // Ninja matches the showIncludes prefix using its raw byte sequence.
+ this->GetRulesFileStream().WriteAltEncoding(
+ showIncludesPrefix, cmGeneratedFileStream::Encoding::ConsoleOutput);
this->GetRulesFileStream() << "\n\n";
}
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index e125470bd..de1d3cda6 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1412,13 +1412,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
// The dependencies must be regenerated.
- std::string targetName = cmSystemTools::GetFilenameName(targetDir);
- targetName = targetName.substr(0, targetName.length() - 4);
- std::string message =
- cmStrCat("Scanning dependencies of target ", targetName);
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
+ if (verbose) {
+ std::string targetName = cmSystemTools::GetFilenameName(targetDir);
+ targetName = targetName.substr(0, targetName.length() - 4);
+ std::string message =
+ cmStrCat("Scanning dependencies of target ", targetName);
+ cmSystemTools::MakefileColorEcho(
+ cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+ }
status = this->ScanDependencies(targetDir, dependFile,
internalDependFile, validDependencies);
@@ -1447,13 +1450,19 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
this->GetBinaryDirectory())
: std::function<bool(const std::string&)>())) {
// regenerate dependencies files
- std::string targetName =
- cmCMakePath(targetDir).GetFileName().RemoveExtension().GenericString();
- auto message = cmStrCat(
- "Consolidate compiler generated dependencies of target ", targetName);
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
+ if (verbose) {
+ std::string targetName = cmCMakePath(targetDir)
+ .GetFileName()
+ .RemoveExtension()
+ .GenericString();
+ auto message =
+ cmStrCat("Consolidate compiler generated dependencies of target ",
+ targetName);
+ cmSystemTools::MakefileColorEcho(
+ cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+ }
// Open the make depends file. This should be copy-if-different
// because the make tool may try to reload it needlessly otherwise.
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 75fe262a0..7bfe3b7ea 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -15,8 +15,8 @@ class cmMakefile;
/** \class cmLocalVisualStudio10Generator
* \brief Write Visual Studio 10 project files.
*
- * cmLocalVisualStudio10Generator produces a Visual Studio 10 project
- * file for each target in its directory.
+ * cmLocalVisualStudio10Generator produces a MSBuild project file for each
+ * target in its directory.
*/
class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator
{
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index f65add19b..af2d31de8 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -195,10 +195,10 @@ void cmLocalVisualStudio7Generator::GenerateTarget(cmGeneratorTarget* target)
this->FortranProject = gg->TargetIsFortranOnly(target);
this->WindowsCEProject = gg->TargetsWindowsCE();
- // Intel Fortran for VS10 uses VS9 format ".vfproj" files.
+ // Intel Fortran always uses VS9 format ".vfproj" files.
cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion();
if (this->FortranProject &&
- gg->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ gg->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS11) {
gg->SetVersion(cmGlobalVisualStudioGenerator::VSVersion::VS9);
}
@@ -680,7 +680,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
langForClCompile = linkLanguage;
if (langForClCompile == "C" || langForClCompile == "CXX" ||
langForClCompile == "Fortran") {
- this->AddLanguageFlags(flags, target, langForClCompile, configName);
+ this->AddLanguageFlags(flags, target, cmBuildStep::Compile,
+ langForClCompile, configName);
}
// set the correct language
if (linkLanguage == "C") {
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index ef1248792..47ad7491b 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -126,7 +126,7 @@ bool cmMacroHelperCommand::operator()(
return false;
}
if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
+ inStatus.SetReturnInvoked(status.GetReturnVariables());
return true;
}
if (status.GetBreakInvoked()) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 469eac3e5..6e0d704f9 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -149,6 +149,29 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace);
}
+Message::LogLevel cmMakefile::GetCurrentLogLevel() const
+{
+ const cmake* cmakeInstance = this->GetCMakeInstance();
+
+ const Message::LogLevel logLevelCliOrDefault = cmakeInstance->GetLogLevel();
+ assert("Expected a valid log level here" &&
+ logLevelCliOrDefault != Message::LogLevel::LOG_UNDEFINED);
+
+ Message::LogLevel result = logLevelCliOrDefault;
+
+ // If the log-level was set via the command line option, it takes precedence
+ // over the CMAKE_MESSAGE_LOG_LEVEL variable.
+ if (!cmakeInstance->WasLogLevelSetViaCLI()) {
+ const Message::LogLevel logLevelFromVar = cmake::StringToLogLevel(
+ this->GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
+ if (logLevelFromVar != Message::LogLevel::LOG_UNDEFINED) {
+ result = logLevelFromVar;
+ }
+ }
+
+ return result;
+}
+
bool cmMakefile::CheckCMP0037(std::string const& targetName,
cmStateEnums::TargetType targetType) const
{
@@ -766,6 +789,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile,
break;
}
if (status.GetReturnInvoked()) {
+ this->RaiseScope(status.GetReturnVariables());
// Exit early due to return command.
break;
}
@@ -1759,7 +1783,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
void cmMakefile::AddSubDirectory(const std::string& srcPath,
const std::string& binPath,
- bool excludeFromAll, bool immediate)
+ bool excludeFromAll, bool immediate,
+ bool system)
{
if (this->DeferRunning) {
this->IssueMessage(
@@ -1789,6 +1814,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
if (excludeFromAll) {
subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
+ if (system) {
+ subMf->SetProperty("SYSTEM", "TRUE");
+ }
if (immediate) {
this->ConfigureSubDirectory(subMf);
@@ -3456,7 +3484,7 @@ void cmMakefile::AddTargetObject(std::string const& tgtName,
#endif
}
-void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
+void cmMakefile::EnableLanguage(std::vector<std::string> const& languages,
bool optional)
{
if (this->DeferRunning) {
@@ -3468,24 +3496,48 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) {
this->AddDefinition("CMAKE_CFG_INTDIR", def);
}
+
+ std::vector<std::string> unique_languages;
+ {
+ std::vector<std::string> duplicate_languages;
+ for (std::string const& language : languages) {
+ if (!cm::contains(unique_languages, language)) {
+ unique_languages.push_back(language);
+ } else if (!cm::contains(duplicate_languages, language)) {
+ duplicate_languages.push_back(language);
+ }
+ }
+ if (!duplicate_languages.empty()) {
+ auto quantity = duplicate_languages.size() == 1 ? std::string(" has")
+ : std::string("s have");
+ this->IssueMessage(MessageType::AUTHOR_WARNING,
+ "Languages to be enabled may not be specified more "
+ "than once at the same time. The following language" +
+ quantity + " been specified multiple times: " +
+ cmJoin(duplicate_languages, ", "));
+ }
+ }
+
// If RC is explicitly listed we need to do it after other languages.
// On some platforms we enable RC implicitly while enabling others.
// Do not let that look like recursive enable_language(RC).
- std::vector<std::string> langs;
- std::vector<std::string> langsRC;
- langs.reserve(lang.size());
- for (std::string const& i : lang) {
- if (i == "RC") {
- langsRC.push_back(i);
+ std::vector<std::string> languages_without_RC;
+ std::vector<std::string> languages_for_RC;
+ languages_without_RC.reserve(unique_languages.size());
+ for (std::string const& language : unique_languages) {
+ if (language == "RC") {
+ languages_for_RC.push_back(language);
} else {
- langs.push_back(i);
+ languages_without_RC.push_back(language);
}
}
- if (!langs.empty()) {
- this->GetGlobalGenerator()->EnableLanguage(langs, this, optional);
+ if (!languages_without_RC.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(languages_without_RC, this,
+ optional);
}
- if (!langsRC.empty()) {
- this->GetGlobalGenerator()->EnableLanguage(langsRC, this, optional);
+ if (!languages_for_RC.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(languages_for_RC, this,
+ optional);
}
}
@@ -4116,6 +4168,18 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef)
#endif
}
+void cmMakefile::RaiseScope(const std::vector<std::string>& variables)
+{
+ for (auto const& varName : variables) {
+ if (this->IsNormalDefinitionSet(varName)) {
+ this->RaiseScope(varName, this->GetDefinition(varName));
+ } else {
+ // unset variable in parent scope
+ this->RaiseScope(varName, nullptr);
+ }
+ }
+}
+
cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
cmStateEnums::TargetType type,
bool global)
@@ -4406,7 +4470,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
}
// Deprecate old policies.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0097 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0102 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
@@ -4471,6 +4535,19 @@ bool cmMakefile::SetPolicyVersion(std::string const& version_min,
cmPolicies::WarnCompat::On);
}
+cmMakefile::VariablePushPop::VariablePushPop(cmMakefile* m)
+ : Makefile(m)
+{
+ this->Makefile->StateSnapshot =
+ this->Makefile->GetState()->CreateVariableScopeSnapshot(
+ this->Makefile->StateSnapshot);
+}
+
+cmMakefile::VariablePushPop::~VariablePushPop()
+{
+ this->Makefile->PopSnapshot();
+}
+
bool cmMakefile::HasCMP0054AlreadyBeenReported(
cmListFileContext const& context) const
{
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 27838b29e..3866aca7f 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -270,7 +270,7 @@ public:
*/
void AddSubDirectory(const std::string& fullSrcDir,
const std::string& fullBinDir, bool excludeFromAll,
- bool immediate);
+ bool immediate, bool system);
void Configure();
@@ -376,6 +376,20 @@ public:
};
friend class PolicyPushPop;
+ /** Helper class to push and pop variables scopes automatically. */
+ class VariablePushPop
+ {
+ public:
+ VariablePushPop(cmMakefile* m);
+ ~VariablePushPop();
+
+ VariablePushPop(VariablePushPop const&) = delete;
+ VariablePushPop& operator=(VariablePushPop const&) = delete;
+
+ private:
+ cmMakefile* Makefile;
+ };
+
/**
* Determine if the given context, name pair has already been reported
* in context of CMP0054.
@@ -861,6 +875,11 @@ public:
void PushScope();
void PopScope();
void RaiseScope(const std::string& var, const char* value);
+ void RaiseScope(const std::string& var, cmValue value)
+ {
+ this->RaiseScope(var, value.GetCStr());
+ }
+ void RaiseScope(const std::vector<std::string>& variables);
// push and pop loop scopes
void PushLoopBlockBarrier();
@@ -924,6 +943,7 @@ public:
};
void IssueMessage(MessageType t, std::string const& text) const;
+ Message::LogLevel GetCurrentLogLevel() const;
/** Set whether or not to report a CMP0000 violation. */
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 3849c6fa4..54f03b9dd 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -136,17 +136,11 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
std::vector<std::string> depends;
this->AppendLinkDepends(depends, linkLanguage);
- // Build a list of compiler flags and linker flags.
- std::string langFlags;
- std::string linkFlags;
-
// Add language feature flags.
+ std::string langFlags;
this->LocalGenerator->AddLanguageFlagsForLinking(
langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
- // Add device-specific linker flags.
- this->GetDeviceLinkFlags(linkFlags, linkLanguage);
-
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;
@@ -173,23 +167,32 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// Set path conversion for link script shells.
this->LocalGenerator->SetLinkScriptShell(useLinkScript);
- std::unique_ptr<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineDeviceComputer> linkLineComputer(
new cmLinkLineDeviceComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetForResponse(useResponseFileForLibs);
linkLineComputer->SetRelink(relink);
+ // Create set of linking flags.
+ std::string linkFlags;
+ std::string ignored_;
+ this->LocalGenerator->GetDeviceLinkFlags(
+ *linkLineComputer, this->GetConfigName(), ignored_, linkFlags, ignored_,
+ ignored_, this->GeneratorTarget);
+
// Collect up flags to link in needed libraries.
std::string linkLibs;
- this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
- useResponseFileForLibs, depends);
+ this->CreateLinkLibs(
+ linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
- this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
- buildObjs, depends, false);
+ this->CreateObjectLists(
+ useLinkScript, false, useResponseFileForObjects, buildObjs, depends,
+ false, cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
cmRulePlaceholderExpander::RuleVariables vars;
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index f30ec2746..45ef8c888 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -287,10 +287,6 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
this->LocalGenerator->AddLanguageFlagsForLinking(
langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
- // Create set of linking flags.
- std::string linkFlags;
- this->GetDeviceLinkFlags(linkFlags, linkLanguage);
-
// Clean files associated with this library.
std::set<std::string> libCleanFiles;
libCleanFiles.insert(
@@ -315,22 +311,31 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
// Collect up flags to link in needed libraries.
std::string linkLibs;
- std::unique_ptr<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineDeviceComputer> linkLineComputer(
new cmLinkLineDeviceComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetForResponse(useResponseFileForLibs);
linkLineComputer->SetRelink(relink);
- this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
- useResponseFileForLibs, depends);
+ // Create set of linking flags.
+ std::string linkFlags;
+ std::string ignored_;
+ this->LocalGenerator->GetDeviceLinkFlags(
+ *linkLineComputer, this->GetConfigName(), ignored_, linkFlags, ignored_,
+ ignored_, this->GeneratorTarget);
+
+ this->CreateLinkLibs(
+ linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
- this->CreateObjectLists(useLinkScript, false, // useArchiveRules
- useResponseFileForObjects, buildObjs, depends,
- false);
+ this->CreateObjectLists(
+ useLinkScript, false, // useArchiveRules
+ useResponseFileForObjects, buildObjs, depends, false,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index aec657734..d19bbb94a 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -46,6 +47,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"
@@ -107,7 +109,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
return result;
}
-std::string cmMakefileTargetGenerator::GetConfigName()
+std::string cmMakefileTargetGenerator::GetConfigName() const
{
auto const& configNames = this->LocalGenerator->GetConfigNames();
assert(configNames.size() == 1);
@@ -190,6 +192,16 @@ void cmMakefileTargetGenerator::CreateRuleFile()
void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
+ this->GeneratorTarget->CheckCxxModuleStatus(this->GetConfigName());
+
+ if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GeneratorTarget->GetName(),
+ "\" target contains C++ module sources which are not supported "
+ "by the generator"));
+ }
+
// -- Write the custom commands for this target
// Evaluates generator expressions and expands prop_value
@@ -302,6 +314,40 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
}
+ std::map<std::string, std::string> file_set_map;
+
+ auto const* tgt = this->GeneratorTarget->Target;
+ for (auto const& name : tgt->GetAllFileSetNames()) {
+ auto const* file_set = tgt->GetFileSet(name);
+ if (!file_set) {
+ this->Makefile->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ continue;
+ }
+
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->LocalGenerator, this->GetConfigName(),
+ this->GeneratorTarget);
+
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files, entry,
+ this->LocalGenerator, this->GetConfigName(),
+ this->GeneratorTarget);
+ }
+
+ for (auto const& it : files) {
+ for (auto const& filename : it.second) {
+ file_set_map[filename] = file_set->GetType();
+ }
+ }
+ }
+
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources,
this->GetConfigName());
@@ -314,6 +360,25 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
this->WriteObjectRuleFiles(*sf);
}
}
+
+ for (cmSourceFile const* sf : objectSources) {
+ auto const& path = sf->GetFullPath();
+ auto const it = file_set_map.find(path);
+ if (it != file_set_map.end()) {
+ auto const& file_set_type = it->second;
+ if (file_set_type == "CXX_MODULES"_s ||
+ file_set_type == "CXX_MODULE_HEADER_UNITS"_s) {
+ if (sf->GetLanguage() != "CXX"_s) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Target \"", tgt->GetName(), "\" contains the source\n ", path,
+ "\nin a file set of type \"", file_set_type,
+ R"(" but the source is not classified as a "CXX" source.)"));
+ }
+ }
+ }
+ }
}
void cmMakefileTargetGenerator::WriteCommonCodeRules()
@@ -977,8 +1042,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
lang == "OBJCXX")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (cmNonempty(clauncher)) {
- compilerLauncher = *clauncher;
+ std::string evaluatedClauncher = cmGeneratorExpression::Evaluate(
+ *clauncher, this->LocalGenerator, config);
+ if (!evaluatedClauncher.empty()) {
+ compilerLauncher = evaluatedClauncher;
}
}
@@ -2080,7 +2147,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
}
std::string cmMakefileTargetGenerator::CreateResponseFile(
- const char* name, std::string const& options,
+ const std::string& name, std::string const& options,
std::vector<std::string>& makefile_depends)
{
// FIXME: Find a better way to determine the response file encoding,
@@ -2126,7 +2193,8 @@ cmMakefileTargetGenerator::CreateLinkLineComputer(
void cmMakefileTargetGenerator::CreateLinkLibs(
cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
- bool useResponseFile, std::vector<std::string>& makefile_depends)
+ bool useResponseFile, std::vector<std::string>& makefile_depends,
+ ResponseFlagFor responseMode)
{
std::string frameworkPath;
std::string linkPath;
@@ -2139,20 +2207,13 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
// Lookup the response file reference flag.
- std::string responseFlagVar =
- cmStrCat("CMAKE_",
- this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
- "_RESPONSE_FILE_LINK_FLAG");
- std::string responseFlag;
- if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
- responseFlag = *p;
- } else {
- responseFlag = "@";
- }
+ std::string responseFlag = this->GetResponseFlag(responseMode);
// Create this response file.
+ std::string responseFileName =
+ (responseMode == Link) ? "linkLibs.rsp" : "deviceLinkLibs.rsp";
std::string link_rsp =
- this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
+ this->CreateResponseFile(responseFileName, linkLibs, makefile_depends);
// Reference the response file.
linkLibs = cmStrCat(responseFlag,
@@ -2164,7 +2225,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
void cmMakefileTargetGenerator::CreateObjectLists(
bool useLinkScript, bool useArchiveRules, bool useResponseFile,
std::string& buildObjs, std::vector<std::string>& makefile_depends,
- bool useWatcomQuote)
+ bool useWatcomQuote, ResponseFlagFor responseMode)
{
std::string variableName;
std::string variableNameExternal;
@@ -2179,27 +2240,19 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->WriteObjectsStrings(object_strings, responseFileLimit);
// Lookup the response file reference flag.
- std::string responseFlagVar =
- cmStrCat("CMAKE_",
- this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
- "_RESPONSE_FILE_LINK_FLAG");
- std::string responseFlag;
- if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
- responseFlag = *p;
- } else {
- responseFlag = "@";
- }
+ std::string responseFlag = this->GetResponseFlag(responseMode);
// Write a response file for each string.
const char* sep = "";
for (unsigned int i = 0; i < object_strings.size(); ++i) {
// Number the response files.
- char rsp[32];
- snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1);
+ std::string responseFileName =
+ (responseMode == Link) ? "objects" : "deviceObjects";
+ responseFileName += std::to_string(i + 1);
// Create this response file.
- std::string objects_rsp =
- this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
+ std::string objects_rsp = this->CreateResponseFile(
+ responseFileName, object_strings[i], makefile_depends);
// Separate from previous response file references.
buildObjs += sep;
@@ -2251,7 +2304,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
}
std::string name = cmStrCat("includes_", lang, ".rsp");
std::string arg = std::move(responseFlag) +
- this->CreateResponseFile(name.c_str(), includeFlags,
+ this->CreateResponseFile(name, includeFlags,
this->FlagFileDepends[lang]);
this->LocalGenerator->AppendFlags(flags, arg);
} else {
@@ -2304,3 +2357,22 @@ void cmMakefileTargetGenerator::GenDefFile(
fout << src->GetFullPath() << "\n";
}
}
+
+std::string cmMakefileTargetGenerator::GetResponseFlag(
+ ResponseFlagFor mode) const
+{
+ std::string responseFlag = "@";
+ std::string responseFlagVar;
+
+ auto lang = this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
+ if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) {
+ responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG");
+ } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) {
+ responseFlagVar = "CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG";
+ }
+
+ if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
+ responseFlag = *p;
+ }
+ return responseFlag;
+}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index cb804e06a..dafa6503d 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -56,7 +56,7 @@ public:
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
- std::string GetConfigName();
+ std::string GetConfigName() const;
protected:
void GetDeviceLinkFlags(std::string& linkFlags,
@@ -157,22 +157,31 @@ protected:
/** Create a response file with the given set of options. Returns
the relative path from the target build working directory to the
response file name. */
- std::string CreateResponseFile(const char* name, std::string const& options,
+ std::string CreateResponseFile(const std::string& name,
+ std::string const& options,
std::vector<std::string>& makefile_depends);
bool CheckUseResponseFileForObjects(std::string const& l) const;
bool CheckUseResponseFileForLibraries(std::string const& l) const;
+ enum ResponseFlagFor
+ {
+ Link,
+ DeviceLink
+ };
+
/** Create list of flags for link libraries. */
void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
std::string& linkLibs, bool useResponseFile,
- std::vector<std::string>& makefile_depends);
+ std::vector<std::string>& makefile_depends,
+ ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Create lists of object files for linking and cleaning. */
void CreateObjectLists(bool useLinkScript, bool useArchiveRules,
bool useResponseFile, std::string& buildObjs,
std::vector<std::string>& makefile_depends,
- bool useWatcomQuote);
+ bool useWatcomQuote,
+ ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Add commands for generate def files */
void GenDefFile(std::vector<std::string>& real_link_commands);
@@ -180,6 +189,9 @@ protected:
void AddIncludeFlags(std::string& flags, const std::string& lang,
const std::string& config) override;
+ /** Return the response flag for the given configuration */
+ std::string GetResponseFlag(ResponseFlagFor mode) const;
+
virtual void CloseFileStreams();
cmLocalUnixMakefileGenerator3* LocalGenerator;
cmGlobalUnixMakefileGenerator3* GlobalGenerator;
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index cd57600fb..fa29ec9a0 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -81,94 +81,83 @@ bool cmMessageCommand(std::vector<std::string> const& args,
auto type = MessageType::MESSAGE;
auto fatal = false;
- auto level = cmake::LogLevel::LOG_UNDEFINED;
+ auto level = Message::LogLevel::LOG_UNDEFINED;
auto checkingType = CheckingType::UNDEFINED;
if (*i == "SEND_ERROR") {
type = MessageType::FATAL_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
++i;
} else if (*i == "FATAL_ERROR") {
fatal = true;
type = MessageType::FATAL_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
++i;
} else if (*i == "WARNING") {
type = MessageType::WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
++i;
} else if (*i == "AUTHOR_WARNING") {
if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
fatal = true;
type = MessageType::AUTHOR_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
} else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
type = MessageType::AUTHOR_WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "CHECK_START") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_START;
++i;
} else if (*i == "CHECK_PASS") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_PASS;
++i;
} else if (*i == "CHECK_FAIL") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_FAIL;
++i;
} else if (*i == "STATUS") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
++i;
} else if (*i == "VERBOSE") {
- level = cmake::LogLevel::LOG_VERBOSE;
+ level = Message::LogLevel::LOG_VERBOSE;
++i;
} else if (*i == "DEBUG") {
- level = cmake::LogLevel::LOG_DEBUG;
+ level = Message::LogLevel::LOG_DEBUG;
++i;
} else if (*i == "TRACE") {
- level = cmake::LogLevel::LOG_TRACE;
+ level = Message::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
fatal = true;
type = MessageType::DEPRECATION_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
} else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
mf.IsOn("CMAKE_WARN_DEPRECATED")) {
type = MessageType::DEPRECATION_WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "NOTICE") {
// `NOTICE` message type is going to be output to stderr
- level = cmake::LogLevel::LOG_NOTICE;
+ level = Message::LogLevel::LOG_NOTICE;
++i;
} else {
// Messages w/o any type are `NOTICE`s
- level = cmake::LogLevel::LOG_NOTICE;
+ level = Message::LogLevel::LOG_NOTICE;
}
assert("Message log level expected to be set" &&
- level != cmake::LogLevel::LOG_UNDEFINED);
-
- auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel();
- assert("Expected a valid log level here" &&
- desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
-
- // Command line option takes precedence over the cache variable
- if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) {
- const auto desiredLevelFromCache =
- cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
- if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) {
- desiredLevel = desiredLevelFromCache;
- }
- }
+ level != Message::LogLevel::LOG_UNDEFINED);
+
+ Message::LogLevel desiredLevel = mf.GetCurrentLogLevel();
if (desiredLevel < level) {
// Suppress the message
@@ -178,17 +167,17 @@ bool cmMessageCommand(std::vector<std::string> const& args,
auto message = cmJoin(cmMakeRange(i, args.cend()), "");
switch (level) {
- case cmake::LogLevel::LOG_ERROR:
- case cmake::LogLevel::LOG_WARNING:
+ case Message::LogLevel::LOG_ERROR:
+ case Message::LogLevel::LOG_WARNING:
// we've overridden the message type, above, so display it directly
mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
break;
- case cmake::LogLevel::LOG_NOTICE:
+ case Message::LogLevel::LOG_NOTICE:
cmSystemTools::Message(IndentText(message, mf));
break;
- case cmake::LogLevel::LOG_STATUS:
+ case Message::LogLevel::LOG_STATUS:
switch (checkingType) {
case CheckingType::CHECK_START:
mf.DisplayStatus(IndentText(message, mf), -1);
@@ -209,9 +198,9 @@ bool cmMessageCommand(std::vector<std::string> const& args,
}
break;
- case cmake::LogLevel::LOG_VERBOSE:
- case cmake::LogLevel::LOG_DEBUG:
- case cmake::LogLevel::LOG_TRACE:
+ case Message::LogLevel::LOG_VERBOSE:
+ case Message::LogLevel::LOG_DEBUG:
+ case Message::LogLevel::LOG_TRACE:
mf.DisplayStatus(IndentText(message, mf), -1);
break;
diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h
index 44de42932..decb4b3b1 100644
--- a/Source/cmMessageType.h
+++ b/Source/cmMessageType.h
@@ -16,3 +16,19 @@ enum class MessageType
DEPRECATION_ERROR,
DEPRECATION_WARNING
};
+
+namespace Message {
+
+/** \brief Define log level constants. */
+enum class LogLevel
+{
+ LOG_UNDEFINED,
+ LOG_ERROR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_STATUS,
+ LOG_VERBOSE,
+ LOG_DEBUG,
+ LOG_TRACE
+};
+}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index d4f160880..bda8a5f48 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -537,7 +537,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
// this target requires separable cuda compilation
// now build the correct command depending on if the target is
// an executable or a dynamic library.
- std::string linkCmd;
switch (this->GetGeneratorTarget()->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
@@ -1086,10 +1085,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
this->GetGeneratorTarget()->GetObjectSources(sources, config);
cmLocalGenerator const* LocalGen = this->GetLocalGenerator();
for (const auto& source : sources) {
+ const std::string sourcePath = source->GetLanguage() == "Swift"
+ ? this->GetCompiledSourceNinjaPath(source)
+ : this->GetObjectFilePath(source, config);
oss << " "
- << LocalGen->ConvertToOutputFormat(
- this->GetCompiledSourceNinjaPath(source),
- cmOutputConverter::SHELL);
+ << LocalGen->ConvertToOutputFormat(sourcePath,
+ cmOutputConverter::SHELL);
}
return oss.str();
}();
@@ -1107,10 +1108,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::vector<cmSourceFile const*> sources;
gt->GetObjectSources(sources, config);
for (const auto& source : sources) {
- linkBuild.Outputs.push_back(
- this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)));
- linkBuild.ExplicitDeps.emplace_back(
- this->GetCompiledSourceNinjaPath(source));
+ if (source->GetLanguage() == "Swift") {
+ linkBuild.Outputs.push_back(
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)));
+ linkBuild.ExplicitDeps.emplace_back(
+ this->GetCompiledSourceNinjaPath(source));
+ } else {
+ linkBuild.ExplicitDeps.emplace_back(
+ this->GetObjectFilePath(source, config));
+ }
}
linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
} else {
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 3fac7f5dc..e4427f5d7 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -21,11 +21,17 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
+#include "cmInstallGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
@@ -36,12 +42,12 @@
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetExport.h"
#include "cmValue.h"
#include "cmake.h"
@@ -153,17 +159,12 @@ std::string cmNinjaTargetGenerator::LanguageDyndepRule(
bool cmNinjaTargetGenerator::NeedCxxModuleSupport(
std::string const& lang, std::string const& config) const
{
- if (lang != "CXX") {
+ if (lang != "CXX"_s) {
return false;
}
- if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
- return false;
- }
- cmGeneratorTarget const* tgt = this->GetGeneratorTarget();
- cmStandardLevelResolver standardResolver(this->Makefile);
- bool const uses_cxx20 =
- standardResolver.HaveStandardAvailable(tgt, "CXX", config, "cxx_std_20");
- return uses_cxx20 && this->GetGlobalGenerator()->CheckCxxModuleSupport();
+ return this->GetGeneratorTarget()->HaveCxxModuleSupport(config) ==
+ cmGeneratorTarget::Cxx20SupportLevel::Supported &&
+ this->GetGlobalGenerator()->CheckCxxModuleSupport();
}
bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang,
@@ -255,51 +256,53 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
}
- if (this->NeedCxxModuleSupport(language, config)) {
- auto const& path = source->GetFullPath();
- auto const* tgt = this->GeneratorTarget->Target;
+ auto const& path = source->GetFullPath();
+ auto const* tgt = this->GeneratorTarget->Target;
- std::string file_set_type;
+ std::string file_set_type;
- for (auto const& name : tgt->GetAllFileSetNames()) {
- auto const* file_set = tgt->GetFileSet(name);
- if (!file_set) {
- this->GetMakefile()->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("Target `", tgt->GetName(),
- "` is tracked to have file set `", name,
- "`, but it was not found."));
- continue;
- }
+ for (auto const& name : tgt->GetAllFileSetNames()) {
+ auto const* file_set = tgt->GetFileSet(name);
+ if (!file_set) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ continue;
+ }
- auto fileEntries = file_set->CompileFileEntries();
- auto directoryEntries = file_set->CompileDirectoryEntries();
- auto directories = file_set->EvaluateDirectoryEntries(
- directoryEntries, this->LocalGenerator, config, this->GeneratorTarget);
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->LocalGenerator, config, this->GeneratorTarget);
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- file_set->EvaluateFileEntry(directories, files, entry,
- this->LocalGenerator, config,
- this->GeneratorTarget);
- }
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files, entry,
+ this->LocalGenerator, config,
+ this->GeneratorTarget);
+ }
- for (auto const& it : files) {
- for (auto const& filename : it.second) {
- if (filename == path) {
- file_set_type = file_set->GetType();
- break;
- }
+ for (auto const& it : files) {
+ for (auto const& filename : it.second) {
+ if (filename == path) {
+ file_set_type = file_set->GetType();
+ break;
}
}
+ }
- if (!file_set_type.empty()) {
- std::string source_type_var = cmStrCat(
- "CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_", file_set_type);
- cmMakefile* mf = this->GetMakefile();
- if (cmValue source_type_flag = mf->GetDefinition(source_type_var)) {
- this->LocalGenerator->AppendFlags(flags, *source_type_flag);
- }
+ if (file_set_type == "CXX_MODULES"_s ||
+ file_set_type == "CXX_MODULE_HEADER_UNITS"_s) {
+ if (source->GetLanguage() != "CXX"_s) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Target \"", tgt->GetName(), "\" contains the source\n ", path,
+ "\nin a file set of type \"", file_set_type,
+ R"(" but the source is not classified as a "CXX" source.)"));
+ continue;
}
}
}
@@ -909,8 +912,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
lang == "OBJCXX")) {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (cmNonempty(clauncher)) {
- compilerLauncher = *clauncher;
+ std::string evaluatedClauncher = cmGeneratorExpression::Evaluate(
+ *clauncher, this->LocalGenerator, config);
+ if (!evaluatedClauncher.empty()) {
+ compilerLauncher = evaluatedClauncher;
}
}
@@ -1038,6 +1043,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
const std::string& config, const std::string& fileConfig,
bool firstForConfig)
{
+ this->GeneratorTarget->CheckCxxModuleStatus(config);
+
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetImplFileStream(fileConfig));
this->GetImplFileStream(fileConfig)
@@ -1338,9 +1345,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
- this->ExportObjectCompileCommand(
- language, sourceFilePath, objectDir, objectFileName, objectFileDir,
- vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ if (firstForConfig) {
+ this->ExportObjectCompileCommand(
+ language, sourceFilePath, objectDir, objectFileName, objectFileDir,
+ vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ }
objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) {
@@ -1616,8 +1625,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
this->Makefile->GetHomeOutputDirectory());
} else if (lang == "CXX") {
- mod_dir =
- cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory);
+ mod_dir = this->GetGlobalGenerator()->ExpandCFGIntDir(
+ cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory),
+ config);
}
if (mod_dir.empty()) {
mod_dir = this->Makefile->GetCurrentBinaryDirectory();
@@ -1654,6 +1664,215 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
tdi_linked_target_dirs.append(l);
}
+ cmTarget* tgt = this->GeneratorTarget->Target;
+ auto all_file_sets = tgt->GetAllFileSetNames();
+ Json::Value& tdi_cxx_module_info = tdi["cxx-modules"] = Json::objectValue;
+ for (auto const& file_set_name : all_file_sets) {
+ auto* file_set = tgt->GetFileSet(file_set_name);
+ if (!file_set) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", file_set_name,
+ "\", but it was not found."));
+ continue;
+ }
+ auto fs_type = file_set->GetType();
+ // We only care about C++ module sources here.
+ if (fs_type != "CXX_MODULES"_s) {
+ continue;
+ }
+
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->GeneratorTarget->LocalGenerator, config,
+ this->GeneratorTarget);
+ std::map<std::string, std::vector<std::string>> files_per_dirs;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files_per_dirs, entry,
+ this->GeneratorTarget->LocalGenerator,
+ config, this->GeneratorTarget);
+ }
+
+ std::map<std::string, cmSourceFile const*> sf_map;
+ {
+ std::vector<cmSourceFile const*> objectSources;
+ this->GeneratorTarget->GetObjectSources(objectSources, config);
+ for (auto const* sf : objectSources) {
+ auto full_path = sf->GetFullPath();
+ if (full_path.empty()) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" has a full path-less source file."));
+ continue;
+ }
+ sf_map[full_path] = sf;
+ }
+ }
+
+ Json::Value fs_dest = Json::nullValue;
+ for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) {
+ if (auto const* fsg =
+ dynamic_cast<cmInstallFileSetGenerator const*>(ig.get())) {
+ if (fsg->GetTarget() == this->GeneratorTarget &&
+ fsg->GetFileSet() == file_set) {
+ fs_dest = fsg->GetDestination(config);
+ continue;
+ }
+ }
+ }
+
+ for (auto const& files_per_dir : files_per_dirs) {
+ for (auto const& file : files_per_dir.second) {
+ auto lookup = sf_map.find(file);
+ if (lookup == sf_map.end()) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(), "\" has source file \"",
+ file,
+ R"(" which is not in any of its "FILE_SET BASE_DIRS".)"));
+ continue;
+ }
+
+ auto const* sf = lookup->second;
+
+ if (!sf) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(), "\" has source file \"",
+ file, "\" which has not been tracked properly."));
+ continue;
+ }
+
+ auto obj_path = this->GetObjectFilePath(sf, config);
+ Json::Value& tdi_module_info = tdi_cxx_module_info[obj_path] =
+ Json::objectValue;
+
+ tdi_module_info["source"] = file;
+ tdi_module_info["relative-directory"] = files_per_dir.first;
+ tdi_module_info["name"] = file_set->GetName();
+ tdi_module_info["type"] = file_set->GetType();
+ tdi_module_info["visibility"] =
+ std::string(cmFileSetVisibilityToName(file_set->GetVisibility()));
+ tdi_module_info["destination"] = fs_dest;
+ }
+ }
+ }
+
+ tdi["config"] = config;
+
+ // Add information about the export sets that this target is a member of.
+ Json::Value& tdi_exports = tdi["exports"] = Json::arrayValue;
+ std::string export_name = this->GeneratorTarget->GetExportName();
+
+ cmInstallCxxModuleBmiGenerator const* bmi_gen = nullptr;
+ for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) {
+ if (auto const* bmig =
+ dynamic_cast<cmInstallCxxModuleBmiGenerator const*>(ig.get())) {
+ if (bmig->GetTarget() == this->GeneratorTarget) {
+ bmi_gen = bmig;
+ continue;
+ }
+ }
+ }
+ if (bmi_gen) {
+ Json::Value tdi_bmi_info = Json::objectValue;
+
+ tdi_bmi_info["permissions"] = bmi_gen->GetFilePermissions();
+ tdi_bmi_info["destination"] = bmi_gen->GetDestination(config);
+ const char* msg_level = "";
+ switch (bmi_gen->GetMessageLevel()) {
+ case cmInstallGenerator::MessageDefault:
+ break;
+ case cmInstallGenerator::MessageAlways:
+ msg_level = "MESSAGE_ALWAYS";
+ break;
+ case cmInstallGenerator::MessageLazy:
+ msg_level = "MESSAGE_LAZY";
+ break;
+ case cmInstallGenerator::MessageNever:
+ msg_level = "MESSAGE_NEVER";
+ break;
+ }
+ tdi_bmi_info["message-level"] = msg_level;
+ tdi_bmi_info["script-location"] = bmi_gen->GetScriptLocation(config);
+
+ tdi["bmi-installation"] = tdi_bmi_info;
+ } else {
+ tdi["bmi-installation"] = Json::nullValue;
+ }
+
+ auto const& all_install_exports =
+ this->GetGlobalGenerator()->GetExportSets();
+ for (auto const& exp : all_install_exports) {
+ // Ignore exports sets which are not for this target.
+ auto const& targets = exp.second.GetTargetExports();
+ auto tgt_export =
+ std::find_if(targets.begin(), targets.end(),
+ [this](std::unique_ptr<cmTargetExport> const& te) {
+ return te->Target == this->GeneratorTarget;
+ });
+ if (tgt_export == targets.end()) {
+ continue;
+ }
+
+ auto const* installs = exp.second.GetInstallations();
+ for (auto const* install : *installs) {
+ Json::Value tdi_export_info = Json::objectValue;
+
+ auto const& ns = install->GetNamespace();
+ auto const& dest = install->GetDestination();
+ auto const& cxxm_dir = install->GetCxxModuleDirectory();
+ auto const& export_prefix = install->GetTempDir();
+
+ tdi_export_info["namespace"] = ns;
+ tdi_export_info["export-name"] = export_name;
+ tdi_export_info["destination"] = dest;
+ tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+ tdi_export_info["export-prefix"] = export_prefix;
+ tdi_export_info["install"] = true;
+
+ tdi_exports.append(tdi_export_info);
+ }
+ }
+
+ auto const& all_build_exports =
+ this->GetMakefile()->GetExportBuildFileGenerators();
+ for (auto const& exp : all_build_exports) {
+ std::vector<std::string> targets;
+ exp->GetTargets(targets);
+
+ // Ignore exports sets which are not for this target.
+ auto const& name = this->GeneratorTarget->GetName();
+ bool has_current_target =
+ std::any_of(targets.begin(), targets.end(),
+ [name](std::string const& tname) { return tname == name; });
+ if (!has_current_target) {
+ continue;
+ }
+
+ Json::Value tdi_export_info = Json::objectValue;
+
+ auto const& ns = exp->GetNamespace();
+ auto const& main_fn = exp->GetMainExportFileName();
+ auto const& cxxm_dir = exp->GetCxxModuleDirectory();
+ auto dest = cmsys::SystemTools::GetParentDirectory(main_fn);
+ auto const& export_prefix =
+ cmSystemTools::GetFilenamePath(exp->GetMainExportFileName());
+
+ tdi_export_info["namespace"] = ns;
+ tdi_export_info["export-name"] = export_name;
+ tdi_export_info["destination"] = dest;
+ tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+ tdi_export_info["export-prefix"] = export_prefix;
+ tdi_export_info["install"] = false;
+
+ tdi_exports.append(tdi_export_info);
+ }
+
std::string const tdin = this->GetTargetDependInfoPath(lang, config);
cmGeneratedFileStream tdif(tdin);
tdif << tdi;
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 688353577..299ab3a43 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -527,6 +527,13 @@ bool cmOutputConverter::Shell_ArgumentNeedsQuotes(cm::string_view in,
}
}
+ /* UNC paths in MinGW Makefiles need quotes. */
+ if ((flags & Shell_Flag_MinGWMake) && (flags & Shell_Flag_Make)) {
+ if (in.size() > 1 && in[0] == '\\' && in[1] == '\\') {
+ return true;
+ }
+ }
+
return false;
}
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 95f3e7e16..7e195664e 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -10,6 +10,7 @@
#include <cm/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -41,11 +42,18 @@ namespace {
using options_map = std::map<std::string, bool>;
using single_map = std::map<std::string, std::string>;
-using multi_map = std::map<std::string, std::vector<std::string>>;
-using options_set = std::set<std::string>;
+using multi_map =
+ std::map<std::string, ArgumentParser::NonEmpty<std::vector<std::string>>>;
+using options_set = std::set<cm::string_view>;
struct UserArgumentParser : public cmArgumentParser<void>
{
+ void BindKeywordsMissingValue(std::vector<cm::string_view>& ref)
+ {
+ this->cmArgumentParser<void>::BindKeywordMissingValue(
+ [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
+ }
+
template <typename T, typename H>
void Bind(std::vector<std::string> const& names,
std::map<std::string, T>& ref, H duplicateKey)
@@ -208,9 +216,10 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,
}
}
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
+ parser.BindKeywordsMissingValue(keywordsMissingValues);
- parser.Parse(list, &unparsed, &keywordsMissingValues);
+ parser.Parse(list, &unparsed);
PassParsedArguments(
prefix, status.GetMakefile(), options, singleValArgs, multiValArgs,
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index cb7402c02..4643868a2 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -421,7 +421,17 @@ class cmMakefile;
SELECT( \
POLICY, CMP0139, \
"The if() command supports path comparisons using PATH_EQUAL operator.", \
- 3, 24, 0, cmPolicies::WARN)
+ 3, 24, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0140, "The return() command checks its arguments.", 3, \
+ 25, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0141, \
+ "MSVC debug information format flags are selected by an abstraction.", 3, \
+ 25, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0142, \
+ "The Xcode generator does not append per-config suffixes to " \
+ "library search paths.", \
+ 3, 25, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -458,7 +468,8 @@ class cmMakefile;
F(CMP0112) \
F(CMP0113) \
F(CMP0119) \
- F(CMP0131)
+ F(CMP0131) \
+ F(CMP0142)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 40f3ab58d..96649ab78 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -1792,13 +1792,16 @@ void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename,
// XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition
// when the Xcode generator supports per-config sources.
if (!this->MultiConfig || this->GlobalGen->IsXcode()) {
- this->AddGeneratedSource(filename.Default, genVars, prepend);
+ cmSourceFile* sf =
+ this->AddGeneratedSource(filename.Default, genVars, prepend);
+ handleSkipPch(sf);
return;
}
for (auto const& cfg : this->ConfigsList) {
std::string const& filenameCfg = filename.Config.at(cfg);
// Register source at makefile
- this->RegisterGeneratedSource(filenameCfg);
+ cmSourceFile* sf = this->RegisterGeneratedSource(filenameCfg);
+ handleSkipPch(sf);
// Add source file to target for this configuration.
this->GenTarget->AddSource(
cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend);
@@ -1847,8 +1850,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
{
- this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName,
- false);
+ this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName);
}
void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
@@ -2159,3 +2161,18 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
return true;
}
+
+void cmQtAutoGenInitializer::handleSkipPch(cmSourceFile* sf)
+{
+ bool skipPch = true;
+ for (auto const& pair : this->AutogenTarget.Sources) {
+ if (!pair.first->GetIsGenerated() &&
+ !pair.first->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ skipPch = false;
+ }
+ }
+
+ if (skipPch) {
+ sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
+ }
+}
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 33749ba74..6d5261a66 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -154,6 +154,8 @@ private:
bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
bool ignoreMissingTarget) const;
+ void handleSkipPch(cmSourceFile* sf);
+
cmQtAutoGenGlobalInitializer* GlobalInitializer = nullptr;
cmGeneratorTarget* GenTarget = nullptr;
cmGlobalGenerator* GlobalGen = nullptr;
diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx
index 59056690c..765b7721d 100644
--- a/Source/cmReturnCommand.cxx
+++ b/Source/cmReturnCommand.cxx
@@ -2,12 +2,52 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmReturnCommand.h"
+#include <cm/string_view>
+#include <cmext/string_view>
+
#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
// cmReturnCommand
-bool cmReturnCommand(std::vector<std::string> const&,
+bool cmReturnCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- status.SetReturnInvoked();
+ if (!args.empty()) {
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0140)) {
+ case cmPolicies::WARN:
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0140), '\n',
+ "return() checks its arguments when the policy is set to NEW. "
+ "Since the policy is not set the OLD behavior will be used so "
+ "the arguments will be ignored."));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ return true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat('\n', cmPolicies::GetPolicyWarning(cmPolicies::CMP0140)));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ default:
+ break;
+ }
+ if (args[0] != "PROPAGATE"_s) {
+ status.SetError(
+ cmStrCat("called with unsupported argument \"", args[0], '"'));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+ status.SetReturnInvoked({ args.begin() + 1, args.end() });
+ } else {
+ status.SetReturnInvoked();
+ }
return true;
}
diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx
index 82a374a83..81ef3da8e 100644
--- a/Source/cmScanDepFormat.cxx
+++ b/Source/cmScanDepFormat.cxx
@@ -188,6 +188,19 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp,
return false;
}
+ if (provide.isMember("is-interface")) {
+ Json::Value const& is_interface = provide["is-interface"];
+ if (!is_interface.isBool()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": is-interface is not a boolean"));
+ return false;
+ }
+ provide_info.IsInterface = is_interface.asBool();
+ } else {
+ provide_info.IsInterface = true;
+ }
+
info->Provides.push_back(provide_info);
}
}
@@ -308,6 +321,8 @@ bool cmScanDepFormat_P1689_Write(std::string const& path,
provide_obj["source-path"] = EncodeFilename(provide.SourcePath);
}
+ provide_obj["is-interface"] = provide.IsInterface;
+
provides.append(provide_obj);
}
diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h
index dae28d950..dc55bf11b 100644
--- a/Source/cmScanDepFormat.h
+++ b/Source/cmScanDepFormat.h
@@ -18,6 +18,11 @@ struct cmSourceReqInfo
std::string SourcePath;
std::string CompiledModulePath;
bool UseSourcePath = false;
+
+ // Provides-only fields.
+ bool IsInterface = true;
+
+ // Requires-only fields.
LookupMethod Method = LookupMethod::ByName;
};
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index 166ee569b..32f9becbd 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -133,7 +133,7 @@ void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
std::string config_test = this->CreateConfigTest(this->Configurations);
os << indent << "if(" << config_test << ")\n";
this->GenerateScriptActions(os, indent.Next());
- os << indent << "endif(" << config_test << ")\n";
+ os << indent << "endif()\n";
}
}
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index db10cd47a..521cf63af 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -9,6 +9,7 @@
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -561,7 +562,8 @@ bool HandleTarget(cmTarget* target, cmMakefile& makefile,
{
// Set or append the property.
if (appendMode) {
- target->AppendProperty(propertyName, propertyValue, appendAsString);
+ target->AppendProperty(propertyName, propertyValue,
+ makefile.GetBacktrace(), appendAsString);
} else {
if (remove) {
target->SetProperty(propertyName, nullptr);
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 785f35667..d2eac0cd7 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -18,6 +18,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -378,25 +379,29 @@ std::unordered_map<std::string, StandardLevelComputer>
"C", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "CXX",
- StandardLevelComputer{
- "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
+ StandardLevelComputer{ "CXX",
+ std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17",
+ "20", "23", "26" } } },
{ "CUDA",
- StandardLevelComputer{
- "CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } },
+ StandardLevelComputer{ "CUDA",
+ std::vector<int>{ 03, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "03", "11", "14", "17",
+ "20", "23", "26" } } },
{ "OBJC",
StandardLevelComputer{
"OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "OBJCXX",
- StandardLevelComputer{
- "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
+ StandardLevelComputer{ "OBJCXX",
+ std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17",
+ "20", "23", "26" } } },
{ "HIP",
- StandardLevelComputer{
- "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }
+ StandardLevelComputer{ "HIP",
+ std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17",
+ "20", "23", "26" } } }
};
}
@@ -416,7 +421,8 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature(
cmTarget* target, const std::string& feature, std::string* error) const
{
if (cmGeneratorExpression::Find(feature) != std::string::npos) {
- target->AppendProperty("COMPILE_FEATURES", feature);
+ target->AppendProperty("COMPILE_FEATURES", feature,
+ this->Makefile->GetBacktrace());
return true;
}
@@ -426,7 +432,8 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature(
return false;
}
- target->AppendProperty("COMPILE_FEATURES", feature);
+ target->AppendProperty("COMPILE_FEATURES", feature,
+ this->Makefile->GetBacktrace());
// FIXME: Add a policy to avoid updating the <LANG>_STANDARD target
// property due to COMPILE_FEATURES. The language standard selection
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 3d38e734a..e54ccfc1a 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -281,7 +281,7 @@ cmStateSnapshot cmState::Reset()
it->CompileOptions.clear();
it->LinkOptions.clear();
it->LinkDirectories.clear();
- it->DirectoryEnd = pos;
+ it->CurrentScope = pos;
it->NormalTargetNames.clear();
it->ImportedTargetNames.clear();
it->Properties.Clear();
@@ -819,7 +819,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
pos->CompileOptionsPosition = 0;
pos->LinkOptionsPosition = 0;
pos->LinkDirectoriesPosition = 0;
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
pos->PolicyScope = this->PolicyStack.Root();
@@ -846,7 +846,7 @@ cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
originSnapshot.Position->BuildSystemDirectory);
pos->ExecutionListFile =
this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->Policies = originSnapshot.Position->Policies;
pos->PolicyRoot = originSnapshot.Position->Policies;
pos->PolicyScope = originSnapshot.Position->Policies;
@@ -876,7 +876,7 @@ cmStateSnapshot cmState::CreateDeferCallSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -891,7 +891,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot(
pos->Keep = false;
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
assert(originSnapshot.Position->Vars.IsValid());
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
@@ -910,7 +910,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -925,7 +925,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -938,6 +938,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot(
pos->ScopeParent = originSnapshot.Position;
pos->SnapshotType = cmStateEnums::VariableScopeType;
pos->Keep = false;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
assert(originSnapshot.Position->Vars.IsValid());
@@ -957,7 +958,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot(
pos->Keep = true;
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -969,7 +970,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
pos->SnapshotType = cmStateEnums::PolicyScopeType;
pos->Keep = false;
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -989,7 +990,7 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
prevPos->BuildSystemDirectory->LinkOptions.size();
prevPos->LinkDirectoriesPosition =
prevPos->BuildSystemDirectory->LinkDirectories.size();
- prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
+ prevPos->BuildSystemDirectory->CurrentScope = prevPos;
if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
if (pos->Vars != prevPos->Vars) {
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index fd46eedfa..ec14834d1 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -62,7 +62,7 @@ struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
struct cmStateDetail::BuildsystemDirectoryStateType
{
- cmStateDetail::PositionType DirectoryEnd;
+ cmStateDetail::PositionType CurrentScope;
std::string Location;
std::string OutputLocation;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index f73df8f08..cb5f11f93 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -64,7 +64,7 @@ bool cmStateSnapshot::IsValid() const
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
{
- return { this->State, this->Position->BuildSystemDirectory->DirectoryEnd };
+ return { this->State, this->Position->BuildSystemDirectory->CurrentScope };
}
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
@@ -76,7 +76,7 @@ cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
if (parentPos != this->State->SnapshotData.Root()) {
snapshot = cmStateSnapshot(this->State,
- parentPos->BuildSystemDirectory->DirectoryEnd);
+ parentPos->BuildSystemDirectory->CurrentScope);
}
return snapshot;
@@ -177,9 +177,9 @@ cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
while (true) {
assert(dir.IsValid());
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf =
- dir->DirectoryEnd->Policies;
+ dir->CurrentScope->Policies;
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
- dir->DirectoryEnd->PolicyRoot;
+ dir->CurrentScope->PolicyRoot;
for (; leaf != root; ++leaf) {
if (parent_scope) {
parent_scope = false;
@@ -190,7 +190,7 @@ cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
return status;
}
}
- cmStateDetail::PositionType e = dir->DirectoryEnd;
+ cmStateDetail::PositionType e = dir->CurrentScope;
cmStateDetail::PositionType p = e->DirectoryParent;
if (p == this->State->SnapshotData.Root()) {
break;
@@ -317,6 +317,25 @@ void cmStateSnapshot::SetDefaultDefinitions()
this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
#endif
+#if defined(__OpenBSD__)
+ this->SetDefinition("BSD", "OpenBSD");
+ this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD");
+#elif defined(__FreeBSD__)
+ this->SetDefinition("BSD", "FreeBSD");
+ this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD");
+#elif defined(__NetBSD__)
+ this->SetDefinition("BSD", "NetBSD");
+ this->SetDefinition("CMAKE_HOST_BSD", "NetBSD");
+#elif defined(__DragonFly__)
+ this->SetDefinition("BSD", "DragonFlyBSD");
+ this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD");
+#endif
+
+#if defined(__linux__)
+ this->SetDefinition("LINUX", "1");
+ this->SetDefinition("CMAKE_HOST_LINUX", "1");
+#endif
+
this->SetDefinition("CMAKE_MAJOR_VERSION",
std::to_string(cmVersion::GetMajorVersion()));
this->SetDefinition("CMAKE_MINOR_VERSION",
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index c3ee6959e..c12d1fe60 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -143,7 +143,8 @@ bool HandleHexCommand(std::vector<std::string> const& args,
std::string::size_type hexIndex = 0;
for (auto const& c : instr) {
- sprintf(&output[hexIndex], "%.2x", static_cast<unsigned char>(c) & 0xFF);
+ snprintf(&output[hexIndex], 3, "%.2x",
+ static_cast<unsigned char>(c) & 0xFF);
hexIndex += 2;
}
@@ -1013,7 +1014,7 @@ int ParseIndex(
Json::ArrayIndex index = static_cast<Json::ArrayIndex>(lindex);
if (index >= max) {
cmAlphaNum sizeStr{ max };
- throw json_error({ "expected an index less then "_s, sizeStr.View(),
+ throw json_error({ "expected an index less than "_s, sizeStr.View(),
" got '"_s, str, "'"_s },
progress);
}
diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx
index 2477d7a33..47082f1fd 100644
--- a/Source/cmSubdirCommand.cxx
+++ b/Source/cmSubdirCommand.cxx
@@ -32,7 +32,7 @@ bool cmSubdirCommand(std::vector<std::string> const& args,
std::string srcPath = mf.GetCurrentSourceDirectory() + "/" + i;
if (cmSystemTools::FileIsDirectory(srcPath)) {
std::string binPath = mf.GetCurrentBinaryDirectory() + "/" + i;
- mf.AddSubDirectory(srcPath, binPath, excludeFromAll, false);
+ mf.AddSubDirectory(srcPath, binPath, excludeFromAll, false, false);
}
// otherwise it is a full path
else if (cmSystemTools::FileIsDirectory(i)) {
@@ -40,7 +40,7 @@ bool cmSubdirCommand(std::vector<std::string> const& args,
// element from the source path and use that
std::string binPath = mf.GetCurrentBinaryDirectory() + "/" +
cmSystemTools::GetFilenameName(i);
- mf.AddSubDirectory(i, binPath, excludeFromAll, false);
+ mf.AddSubDirectory(i, binPath, excludeFromAll, false, false);
} else {
status.SetError(cmStrCat("Incorrect SUBDIRS command. Directory: ", i,
" does not exist."));
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index f077801da..ee7490812 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -11,11 +11,17 @@
// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 700
#endif
+#if defined(__APPLE__)
+// Restore Darwin APIs removed by _POSIX_C_SOURCE.
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
+# define _DARWIN_C_SOURCE
+#endif
#include "cmSystemTools.h"
#include <cm/optional>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include <cm3p/uv.h>
@@ -87,7 +93,6 @@
# include <unistd.h>
# include <sys/time.h>
-# include <sys/types.h>
#endif
#if defined(_WIN32) && \
@@ -1000,6 +1005,93 @@ void cmSystemTools::InitializeLibUV()
#endif
}
+#if defined(_WIN32)
+# include <random>
+
+# include <wctype.h>
+# ifdef _MSC_VER
+using mode_t = cmSystemTools::SystemTools::mode_t;
+# endif
+#else
+# include <sys/stat.h>
+#endif
+
+inline int Mkdir(const char* dir, const mode_t* mode)
+{
+#if defined(_WIN32)
+ int ret = _wmkdir(cmSystemTools::ConvertToWindowsExtendedPath(dir).c_str());
+ if (ret == 0 && mode)
+ cmSystemTools::SystemTools::SetPermissions(dir, *mode);
+ return ret;
+#else
+ return mkdir(dir, mode ? *mode : 0777);
+#endif
+}
+
+cmsys::Status cmSystemTools::MakeTempDirectory(std::string& path,
+ const mode_t* mode)
+{
+ if (path.empty()) {
+ return cmsys::Status::POSIX(EINVAL);
+ }
+ return cmSystemTools::MakeTempDirectory(&path.front(), mode);
+}
+
+cmsys::Status cmSystemTools::MakeTempDirectory(char* path, const mode_t* mode)
+{
+ if (!path) {
+ return cmsys::Status::POSIX(EINVAL);
+ }
+
+ // verify that path ends with "XXXXXX"
+ const auto l = std::strlen(path);
+ if (!cmHasLiteralSuffix(cm::string_view{ path, l }, "XXXXXX")) {
+ return cmsys::Status::POSIX(EINVAL);
+ }
+
+ // create parent directories
+ auto* sep = path;
+ while ((sep = strchr(sep, '/'))) {
+ // all underlying functions use C strings,
+ // so temporarily end the string here
+ *sep = '\0';
+ Mkdir(path, mode);
+
+ *sep = '/';
+ ++sep;
+ }
+
+#ifdef _WIN32
+ const int nchars = 36;
+ const char chars[nchars + 1] = "abcdefghijklmnopqrstuvwxyz0123456789";
+
+ std::random_device rd;
+ std::mt19937 rg{ rd() };
+ std::uniform_int_distribution<int> dist{ 0, nchars - 1 };
+
+ for (auto tries = 100; tries; --tries) {
+ for (auto n = l - 6; n < l; ++n) {
+ path[n] = chars[dist(rg)];
+ }
+ if (Mkdir(path, mode) == 0) {
+ return cmsys::Status::Success();
+ } else if (errno != EEXIST) {
+ return cmsys::Status::POSIX_errno();
+ }
+ }
+ return cmsys::Status::POSIX(EAGAIN);
+#else
+ if (mkdtemp(path)) {
+ if (mode) {
+ chmod(path, *mode);
+ }
+ } else {
+ return cmsys::Status::POSIX_errno();
+ }
+ return cmsys::Status::Success();
+#endif
+}
+
#ifdef _WIN32
namespace {
bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
@@ -1256,7 +1348,7 @@ std::string cmSystemTools::ComputeCertificateThumbprint(
certContext, CERT_HASH_PROP_ID, hashData, &hashLength)) {
for (DWORD i = 0; i < hashLength; i++) {
// Convert each byte to hexadecimal
- sprintf(pHashPrint, "%02X", hashData[i]);
+ snprintf(pHashPrint, 3, "%02X", hashData[i]);
pHashPrint += 2;
}
*pHashPrint = '\0';
@@ -1539,8 +1631,7 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top,
bool cmSystemTools::UnsetEnv(const char* value)
{
# if !defined(HAVE_UNSETENV)
- std::string var = cmStrCat(value, '=');
- return cmSystemTools::PutEnv(var);
+ return cmSystemTools::UnPutEnv(value);
# else
unsetenv(value);
return true;
@@ -1551,9 +1642,18 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
{
std::vector<std::string> env;
int cc;
+# ifdef _WIN32
+ // if program starts with main, _wenviron is initially NULL, call to
+ // _wgetenv and create wide-character string environment
+ _wgetenv(L"");
+ for (cc = 0; _wenviron[cc]; ++cc) {
+ env.emplace_back(cmsys::Encoding::ToNarrow(_wenviron[cc]));
+ }
+# else
for (cc = 0; environ[cc]; ++cc) {
env.emplace_back(environ[cc]);
}
+# endif
return env;
}
@@ -1564,6 +1664,144 @@ void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
}
}
+void cmSystemTools::EnvDiff::AppendEnv(std::vector<std::string> const& env)
+{
+ for (std::string const& eit : env) {
+ this->PutEnv(eit);
+ }
+}
+
+void cmSystemTools::EnvDiff::PutEnv(const std::string& env)
+{
+ auto const eq_loc = env.find('=');
+ if (eq_loc != std::string::npos) {
+ std::string name = env.substr(0, eq_loc);
+ diff[name] = env.substr(eq_loc + 1);
+ } else {
+ this->UnPutEnv(env);
+ }
+}
+
+void cmSystemTools::EnvDiff::UnPutEnv(const std::string& env)
+{
+ diff[env] = {};
+}
+
+bool cmSystemTools::EnvDiff::ParseOperation(const std::string& envmod)
+{
+ char path_sep = GetSystemPathlistSeparator();
+
+ auto apply_diff = [this](const std::string& name,
+ std::function<void(std::string&)> const& apply) {
+ cm::optional<std::string> old_value = diff[name];
+ std::string output;
+ if (old_value) {
+ output = *old_value;
+ } else {
+ const char* curval = cmSystemTools::GetEnv(name);
+ if (curval) {
+ output = curval;
+ }
+ }
+ apply(output);
+ diff[name] = output;
+ };
+
+ // Split on `=`
+ auto const eq_loc = envmod.find_first_of('=');
+ if (eq_loc == std::string::npos) {
+ cmSystemTools::Error(cmStrCat(
+ "Error: Missing `=` after the variable name in: ", envmod, '\n'));
+ return false;
+ }
+
+ auto const name = envmod.substr(0, eq_loc);
+
+ // Split value on `:`
+ auto const op_value_start = eq_loc + 1;
+ auto const colon_loc = envmod.find_first_of(':', op_value_start);
+ if (colon_loc == std::string::npos) {
+ cmSystemTools::Error(
+ cmStrCat("Error: Missing `:` after the operation in: ", envmod, '\n'));
+ return false;
+ }
+ auto const op = envmod.substr(op_value_start, colon_loc - op_value_start);
+
+ auto const value_start = colon_loc + 1;
+ auto const value = envmod.substr(value_start);
+
+ // Determine what to do with the operation.
+ if (op == "reset"_s) {
+ auto entry = diff.find(name);
+ if (entry != diff.end()) {
+ diff.erase(entry);
+ }
+ } else if (op == "set"_s) {
+ diff[name] = value;
+ } else if (op == "unset"_s) {
+ diff[name] = {};
+ } else if (op == "string_append"_s) {
+ apply_diff(name, [&value](std::string& output) { output += value; });
+ } else if (op == "string_prepend"_s) {
+ apply_diff(name,
+ [&value](std::string& output) { output.insert(0, value); });
+ } else if (op == "path_list_append"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output += path_sep;
+ }
+ output += value;
+ });
+ } else if (op == "path_list_prepend"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), path_sep);
+ }
+ output.insert(0, value);
+ });
+ } else if (op == "cmake_list_append"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output += ';';
+ }
+ output += value;
+ });
+ } else if (op == "cmake_list_prepend"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), ';');
+ }
+ output.insert(0, value);
+ });
+ } else {
+ cmSystemTools::Error(cmStrCat(
+ "Error: Unrecognized environment manipulation argument: ", op, '\n'));
+ return false;
+ }
+
+ return true;
+}
+
+void cmSystemTools::EnvDiff::ApplyToCurrentEnv(std::ostringstream* measurement)
+{
+ for (auto const& env_apply : diff) {
+ if (env_apply.second) {
+ auto const env_update =
+ cmStrCat(env_apply.first, '=', *env_apply.second);
+ cmSystemTools::PutEnv(env_update);
+ if (measurement) {
+ *measurement << env_update << std::endl;
+ }
+ } else {
+ cmSystemTools::UnsetEnv(env_apply.first.c_str());
+ if (measurement) {
+ // Signify that this variable is being actively unset
+ *measurement << '#' << env_apply.first << "=\n";
+ }
+ }
+ }
+}
+
cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
{
this->Env = cmSystemTools::GetEnvironmentVariables();
@@ -3352,8 +3590,19 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes)
}
cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName,
- std::string const& newName,
- std::string* errorMessage)
+ std::string const& newName)
+{
+ cmsys::Status status =
+ cmSystemTools::CreateSymlinkQuietly(origName, newName);
+ if (!status) {
+ cmSystemTools::Error(cmStrCat("failed to create symbolic link '", newName,
+ "': ", status.GetString()));
+ }
+ return status;
+}
+
+cmsys::Status cmSystemTools::CreateSymlinkQuietly(std::string const& origName,
+ std::string const& newName)
{
uv_fs_t req;
int flags = 0;
@@ -3373,20 +3622,23 @@ cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName,
#else
status = cmsys::Status::POSIX(-err);
#endif
- std::string e = cmStrCat("failed to create symbolic link '", newName,
- "': ", status.GetString());
- if (errorMessage) {
- *errorMessage = std::move(e);
- } else {
- cmSystemTools::Error(e);
- }
}
return status;
}
cmsys::Status cmSystemTools::CreateLink(std::string const& origName,
- std::string const& newName,
- std::string* errorMessage)
+ std::string const& newName)
+{
+ cmsys::Status status = cmSystemTools::CreateLinkQuietly(origName, newName);
+ if (!status) {
+ cmSystemTools::Error(
+ cmStrCat("failed to create link '", newName, "': ", status.GetString()));
+ }
+ return status;
+}
+
+cmsys::Status cmSystemTools::CreateLinkQuietly(std::string const& origName,
+ std::string const& newName)
{
uv_fs_t req;
int err =
@@ -3400,13 +3652,6 @@ cmsys::Status cmSystemTools::CreateLink(std::string const& origName,
#else
status = cmsys::Status::POSIX(-err);
#endif
- std::string e =
- cmStrCat("failed to create link '", newName, "': ", status.GetString());
- if (errorMessage) {
- *errorMessage = std::move(e);
- } else {
- cmSystemTools::Error(e);
- }
}
return status;
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index ec650f743..87b354c8d 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -4,11 +4,18 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#if !defined(_WIN32)
+# include <sys/types.h>
+#endif
+
#include <cstddef>
#include <functional>
+#include <map>
+#include <sstream>
#include <string>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include "cmsys/Process.h"
@@ -148,6 +155,27 @@ public:
Failure,
};
+#if defined(_MSC_VER)
+ /** Visual C++ does not define mode_t. */
+ using mode_t = unsigned short;
+#endif
+
+ /**
+ * Make a new temporary directory. The path must end in "XXXXXX", and will
+ * be modified to reflect the name of the directory created. This function
+ * is similar to POSIX mkdtemp (and is implemented using the same where that
+ * function is available).
+ *
+ * This function can make a full path even if none of the directories existed
+ * prior to calling this function.
+ *
+ * Note that this function may modify \p path even if it does not succeed.
+ */
+ static cmsys::Status MakeTempDirectory(char* path,
+ const mode_t* mode = nullptr);
+ static cmsys::Status MakeTempDirectory(std::string& path,
+ const mode_t* mode = nullptr);
+
/** Copy a file. */
static bool CopySingleFile(const std::string& oldname,
const std::string& newname);
@@ -377,6 +405,42 @@ public:
/** Append multiple variables to the current environment. */
static void AppendEnv(std::vector<std::string> const& env);
+ /**
+ * Helper class to represent an environment diff directly. This is to avoid
+ * repeated in-place environment modification (i.e. via setenv/putenv), which
+ * could be slow.
+ */
+ class EnvDiff
+ {
+ public:
+ /** Append multiple variables to the current environment diff */
+ void AppendEnv(std::vector<std::string> const& env);
+
+ /**
+ * Add a single variable (or remove if no = sign) to the current
+ * environment diff.
+ */
+ void PutEnv(const std::string& env);
+
+ /** Remove a single variable from the current environment diff. */
+ void UnPutEnv(const std::string& env);
+
+ /**
+ * Apply an ENVIRONMENT_MODIFICATION operation to this diff. Returns
+ * false and issues an error on parse failure.
+ */
+ bool ParseOperation(const std::string& envmod);
+
+ /**
+ * Apply this diff to the actual environment, optionally writing out the
+ * modifications to a CTest-compatible measurement stream.
+ */
+ void ApplyToCurrentEnv(std::ostringstream* measurement = nullptr);
+
+ private:
+ std::map<std::string, cm::optional<std::string>> diff;
+ };
+
/** Helper class to save and restore the environment.
Instantiate this class as an automatic variable on
the stack. Its constructor saves a copy of the current
@@ -531,14 +595,16 @@ public:
/** Create a symbolic link if the platform supports it. Returns whether
creation succeeded. */
static cmsys::Status CreateSymlink(std::string const& origName,
- std::string const& newName,
- std::string* errorMessage = nullptr);
+ std::string const& newName);
+ static cmsys::Status CreateSymlinkQuietly(std::string const& origName,
+ std::string const& newName);
/** Create a hard link if the platform supports it. Returns whether
creation succeeded. */
static cmsys::Status CreateLink(std::string const& origName,
- std::string const& newName,
- std::string* errorMessage = nullptr);
+ std::string const& newName);
+ static cmsys::Status CreateLinkQuietly(std::string const& origName,
+ std::string const& newName);
/** Get the system name. */
static cm::string_view GetSystemName();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index cbe5d7d8d..874195b0c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -272,6 +272,8 @@ public:
cmListFileBacktrace Backtrace;
FileSetType HeadersFileSets;
+ FileSetType CxxModulesFileSets;
+ FileSetType CxxModuleHeadersFileSets;
cmTargetInternals();
@@ -293,6 +295,12 @@ public:
cm::string_view fileSetType) const;
cmValue GetFileSetPaths(cmTarget const* self, std::string const& fileSetName,
cm::string_view fileSetType) const;
+
+ cmListFileBacktrace GetBacktrace(
+ cm::optional<cmListFileBacktrace> const& bt) const
+ {
+ return bt ? *bt : this->Makefile->GetBacktrace();
+ }
};
cmTargetInternals::cmTargetInternals()
@@ -301,6 +309,19 @@ cmTargetInternals::cmTargetInternals()
"The default header set"_s, "Header set"_s,
FileSetEntries("HEADER_SETS"_s),
FileSetEntries("INTERFACE_HEADER_SETS"_s))
+ , CxxModulesFileSets("CXX_MODULES"_s, "CXX_MODULE_DIRS"_s,
+ "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
+ "CXX_MODULE_SET_"_s, "C++ module"_s,
+ "The default C++ module set"_s, "C++ module set"_s,
+ FileSetEntries("CXX_MODULE_SETS"_s),
+ FileSetEntries("INTERFACE_CXX_MODULE_SETS"_s))
+ , CxxModuleHeadersFileSets(
+ "CXX_MODULE_HEADER_UNITS"_s, "CXX_MODULE_HEADER_UNIT_DIRS"_s,
+ "CXX_MODULE_HEADER_UNIT_SET"_s, "CXX_MODULE_HEADER_UNIT_DIRS_"_s,
+ "CXX_MODULE_HEADER_UNIT_SET_"_s, "C++ module header"_s,
+ "The default C++ module header set"_s, "C++ module header set"_s,
+ FileSetEntries("CXX_MODULE_HEADER_UNIT_SETS"_s),
+ FileSetEntries("INTERFACE_CXX_MODULE_HEADER_UNIT_SETS"_s))
{
}
@@ -542,6 +563,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("AUTORCC_OPTIONS");
initProp("LINK_DEPENDS_NO_SHARED");
initProp("LINK_INTERFACE_LIBRARIES");
+ initProp("MSVC_DEBUG_INFORMATION_FORMAT");
initProp("MSVC_RUNTIME_LIBRARY");
initProp("WATCOM_RUNTIME_LIBRARY");
initProp("WIN32_EXECUTABLE");
@@ -605,12 +627,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
+ initProp("XCODE_SCHEME_LAUNCH_CONFIGURATION");
+ initProp("XCODE_SCHEME_ENABLE_GPU_API_VALIDATION");
+ initProp("XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION");
initProp("XCODE_SCHEME_WORKING_DIRECTORY");
initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER");
initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
initProp("XCODE_SCHEME_GUARD_MALLOC");
+ initProp("XCODE_SCHEME_LAUNCH_MODE");
initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
initProp("XCODE_SCHEME_MALLOC_STACK");
initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
@@ -760,6 +786,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
}
+ if (this->IsImported() || mf->GetPropertyAsBool("SYSTEM")) {
+ this->SetProperty("SYSTEM", "ON");
+ }
+
for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
if (prop.first.second == cmProperty::TARGET &&
!prop.second.GetInitializeFromVariable().empty()) {
@@ -1223,7 +1253,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
? targetNameGenex(lib)
: lib;
this->AppendProperty("LINK_LIBRARIES",
- this->GetDebugGeneratorExpressions(libName, llt));
+ this->GetDebugGeneratorExpressions(libName, llt),
+ mf.GetBacktrace());
}
if (cmGeneratorExpression::Find(lib) != std::string::npos ||
@@ -1367,11 +1398,32 @@ cmBTStringRange cmTarget::GetHeaderSetsEntries() const
return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries);
}
+cmBTStringRange cmTarget::GetCxxModuleSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModulesFileSets.SelfEntries.Entries);
+}
+
+cmBTStringRange cmTarget::GetCxxModuleHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModuleHeadersFileSets.SelfEntries.Entries);
+}
+
cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
{
return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries);
}
+cmBTStringRange cmTarget::GetInterfaceCxxModuleSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+}
+
+cmBTStringRange cmTarget::GetInterfaceCxxModuleHeaderSetsEntries() const
+{
+ return cmMakeRange(
+ this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
+}
+
namespace {
#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
MAKE_PROP(C_STANDARD);
@@ -1631,13 +1683,21 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
} else if (this->impl->HeadersFileSets.WriteProperties(
this, this->impl.get(), prop, value, true)) {
/* Handled in the `if` condition. */
+ } else if (this->impl->CxxModulesFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, true)) {
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, true)) {
+ /* Handled in the `if` condition. */
} else {
this->impl->Properties.SetProperty(prop, value);
}
}
void cmTarget::AppendProperty(const std::string& prop,
- const std::string& value, bool asString)
+ const std::string& value,
+ cm::optional<cmListFileBacktrace> const& bt,
+ bool asString)
{
if (prop == "NAME") {
this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
@@ -1668,32 +1728,32 @@ void cmTarget::AppendProperty(const std::string& prop,
}
if (prop == "INCLUDE_DIRECTORIES") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_OPTIONS") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->CompileOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_FEATURES") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->CompileFeaturesEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_DEFINITIONS") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_OPTIONS") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_DIRECTORIES") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == "PRECOMPILE_HEADERS") {
@@ -1706,32 +1766,32 @@ void cmTarget::AppendProperty(const std::string& prop,
return;
}
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_LIBRARIES") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES) {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
if (!value.empty()) {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
lfbt);
}
} else if (prop == "SOURCES") {
- cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
this->impl->SourceEntries.emplace_back(value, lfbt);
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
this->impl->Makefile->IssueMessage(
@@ -1742,6 +1802,13 @@ void cmTarget::AppendProperty(const std::string& prop,
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be appended.");
} else if (this->impl->HeadersFileSets.WriteProperties(
+ this, this->impl.get(), prop, value,
+ false)) { // NOLINT(bugprone-branch-clone)
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModulesFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, false)) {
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
this, this->impl.get(), prop, value, false)) {
/* Handled in the `if` condition. */
} else {
@@ -2307,6 +2374,17 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
if (headers.first) {
return headers.second;
}
+ auto cxx_modules = this->impl->CxxModulesFileSets.ReadProperties(
+ this, this->impl.get(), prop);
+ if (cxx_modules.first) {
+ return cxx_modules.second;
+ }
+ auto cxx_module_headers =
+ this->impl->CxxModuleHeadersFileSets.ReadProperties(
+ this, this->impl.get(), prop);
+ if (cxx_module_headers.first) {
+ return cxx_module_headers.second;
+ }
}
cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
@@ -2584,6 +2662,11 @@ std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
auto bt = this->impl->Makefile->GetBacktrace();
if (type == this->impl->HeadersFileSets.TypeName) {
this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt));
+ } else if (type == this->impl->CxxModulesFileSets.TypeName) {
+ this->impl->CxxModulesFileSets.AddFileSet(name, vis, std::move(bt));
+ } else if (type == this->impl->CxxModuleHeadersFileSets.TypeName) {
+ this->impl->CxxModuleHeadersFileSets.AddFileSet(name, vis,
+ std::move(bt));
}
}
return std::make_pair(&result.first->second, result.second);
@@ -2594,6 +2677,12 @@ std::string cmTarget::GetFileSetsPropertyName(const std::string& type)
if (type == "HEADERS") {
return "HEADER_SETS";
}
+ if (type == "CXX_MODULES") {
+ return "CXX_MODULE_SETS";
+ }
+ if (type == "CXX_MODULE_HEADER_UNITS") {
+ return "CXX_MODULE_HEADER_UNIT_SETS";
+ }
return "";
}
@@ -2602,6 +2691,12 @@ std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type)
if (type == "HEADERS") {
return "INTERFACE_HEADER_SETS";
}
+ if (type == "CXX_MODULES") {
+ return "INTERFACE_CXX_MODULE_SETS";
+ }
+ if (type == "CXX_MODULE_HEADER_UNITS") {
+ return "INTERFACE_CXX_MODULE_HEADER_UNIT_SETS";
+ }
return "";
}
@@ -2629,6 +2724,8 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
};
appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries);
+ appendEntries(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+ appendEntries(this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
return result;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 467c4dabd..38bd0365a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -185,8 +185,10 @@ public:
{
this->SetProperty(prop, cmValue(value));
}
- void AppendProperty(const std::string& prop, const std::string& value,
- bool asString = false);
+ void AppendProperty(
+ const std::string& prop, const std::string& value,
+ cm::optional<cmListFileBacktrace> const& bt = cm::nullopt,
+ bool asString = false);
//! Might return a nullptr if the property is not set or invalid
cmValue GetProperty(const std::string& prop) const;
//! Always returns a valid pointer
@@ -281,8 +283,12 @@ public:
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
cmBTStringRange GetHeaderSetsEntries() const;
+ cmBTStringRange GetCxxModuleSetsEntries() const;
+ cmBTStringRange GetCxxModuleHeaderSetsEntries() const;
cmBTStringRange GetInterfaceHeaderSetsEntries() const;
+ cmBTStringRange GetInterfaceCxxModuleSetsEntries() const;
+ cmBTStringRange GetInterfaceCxxModuleHeaderSetsEntries() const;
std::string ImportedGetFullPath(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index b56b245de..268bfacb8 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetCompileDefinitionsCommand.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
@@ -28,7 +29,8 @@ private:
const std::vector<std::string>& content,
bool /*prepend*/, bool /*system*/) override
{
- tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content));
+ tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content),
+ this->Makefile->GetBacktrace());
return true; // Successfully handled.
}
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 885ac7451..1cef88866 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -8,6 +8,7 @@
class cmFileSet;
class cmGeneratorTarget;
+class cmInstallCxxModuleBmiGenerator;
class cmInstallFileSetGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
@@ -32,6 +33,7 @@ public:
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators;
+ cmInstallCxxModuleBmiGenerator* CxxModuleBmiGenerator;
///@}
bool NamelinkOnly = false;
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index b4b43197c..cb8387397 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -88,7 +88,8 @@ void TargetIncludeDirectoriesImpl::HandleInterfaceContent(
system);
if (system) {
std::string joined = this->Join(content);
- tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined);
+ tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined,
+ this->Makefile->GetBacktrace());
}
}
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index af870dada..0b123b2d6 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -622,7 +622,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState,
void TLL::AppendProperty(std::string const& prop, std::string const& value)
{
this->AffectsProperty(prop);
- this->Target->AppendProperty(prop, value);
+ this->Target->AppendProperty(prop, value, this->Makefile.GetBacktrace());
}
void TLL::AffectsProperty(std::string const& prop)
@@ -633,14 +633,16 @@ void TLL::AffectsProperty(std::string const& prop)
// Add a wrapper to the expression to tell LookupLinkItem to look up
// names in the caller's directory.
if (this->Props.insert(prop).second) {
- this->Target->AppendProperty(prop, this->DirectoryId);
+ this->Target->AppendProperty(prop, this->DirectoryId,
+ this->Makefile.GetBacktrace());
}
}
TLL::~TLL()
{
for (std::string const& prop : this->Props) {
- this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP);
+ this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP,
+ this->Makefile.GetBacktrace());
}
}
diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx
index a5066cc2a..4dd158d28 100644
--- a/Source/cmTargetPrecompileHeadersCommand.cxx
+++ b/Source/cmTargetPrecompileHeadersCommand.cxx
@@ -5,6 +5,7 @@
#include <utility>
#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
@@ -48,7 +49,8 @@ private:
{
std::string const& base = this->Makefile->GetCurrentSourceDirectory();
tgt->AppendProperty("PRECOMPILE_HEADERS",
- this->Join(ConvertToAbsoluteContent(content, base)));
+ this->Join(ConvertToAbsoluteContent(content, base)),
+ this->Makefile->GetBacktrace());
return true;
}
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index b1367e184..53e25b5d3 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -9,6 +9,8 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmExperimental.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
@@ -27,8 +29,8 @@ struct FileSetArgs
{
std::string Type;
std::string FileSet;
- std::vector<std::string> BaseDirs;
- std::vector<std::string> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> BaseDirs;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Files;
};
auto const FileSetArgsParser = cmArgumentParser<FileSetArgs>()
@@ -77,7 +79,8 @@ private:
{
tgt->AppendProperty("SOURCES",
this->Join(this->ConvertToAbsoluteContent(
- tgt, content, IsInterface::No, CheckCMP0076::Yes)));
+ tgt, content, IsInterface::No, CheckCMP0076::Yes)),
+ this->Makefile->GetBacktrace());
return true; // Successfully handled.
}
@@ -196,7 +199,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
bool TargetSourcesImpl::HandleFileSetMode(
const std::string& scope, const std::vector<std::string>& content)
{
- auto args = FileSetsArgsParser.Parse(content);
+ auto args = FileSetsArgsParser.Parse(content, /*unparsedArguments=*/nullptr);
for (auto& argList : args.FileSets) {
argList.emplace(argList.begin(), "FILE_SET"_s);
@@ -256,9 +259,31 @@ bool TargetSourcesImpl::HandleOneFileSet(
this->SetError("Must specify a TYPE when creating file set");
return false;
}
- if (type != "HEADERS"_s) {
- this->SetError("File set TYPE may only be \"HEADERS\"");
- return false;
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+
+ if (supportCxx20FileSetTypes) {
+ if (type != "HEADERS"_s && type != "CXX_MODULES"_s &&
+ type != "CXX_MODULE_HEADER_UNITS"_s) {
+ this->SetError(
+ R"(File set TYPE may only be "HEADERS", "CXX_MODULES", or "CXX_MODULE_HEADER_UNITS")");
+ return false;
+ }
+
+ if (cmFileSetVisibilityIsForInterface(visibility) &&
+ !cmFileSetVisibilityIsForSelf(visibility) &&
+ !this->Target->IsImported()) {
+ if (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s) {
+ this->SetError(
+ R"(File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS" may not have "INTERFACE" visibility)");
+ return false;
+ }
+ }
+ } else {
+ if (type != "HEADERS"_s) {
+ this->SetError("File set TYPE may only be \"HEADERS\"");
+ return false;
+ }
}
if (args.BaseDirs.empty()) {
@@ -294,17 +319,19 @@ bool TargetSourcesImpl::HandleOneFileSet(
if (!baseDirectories.empty()) {
fileSet.first->AddDirectoryEntry(
BT<std::string>(baseDirectories, this->Makefile->GetBacktrace()));
- if (type == "HEADERS"_s) {
+ if (type == "HEADERS"_s || type == "CXX_MODULE_HEADER_UNITS"_s) {
for (auto const& dir : cmExpandedList(baseDirectories)) {
auto interfaceDirectoriesGenex =
cmStrCat("$<BUILD_INTERFACE:", dir, ">");
if (cmFileSetVisibilityIsForSelf(visibility)) {
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
- interfaceDirectoriesGenex);
+ interfaceDirectoriesGenex,
+ this->Makefile->GetBacktrace());
}
if (cmFileSetVisibilityIsForInterface(visibility)) {
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
- interfaceDirectoriesGenex);
+ interfaceDirectoriesGenex,
+ this->Makefile->GetBacktrace());
}
}
}
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index 130c2288a..a2c4ce123 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/Source/cmTryCompileCommand.cxx
@@ -2,34 +2,69 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTryCompileCommand.h"
+#include "cmCoreTryCompile.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmValue.h"
#include "cmake.h"
-class cmExecutionStatus;
-
-// cmTryCompileCommand
-bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv,
- cmExecutionStatus&)
+bool cmTryCompileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (argv.size() < 3) {
+ cmMakefile& mf = status.GetMakefile();
+
+ if (args.size() < 3) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The try_compile() command requires at least 3 arguments.");
return false;
}
- if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
- cmake::FIND_PACKAGE_MODE) {
- this->Makefile->IssueMessage(
+ if (mf.GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) {
+ mf.IssueMessage(
MessageType::FATAL_ERROR,
"The try_compile() command is not supported in --find-package mode.");
return false;
}
- this->TryCompileCode(argv, false);
+ cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
+ cmValue tt = mf.GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
+ if (cmNonempty(tt)) {
+ if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) {
+ targetType = cmStateEnums::EXECUTABLE;
+ } else if (*tt ==
+ cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) {
+ targetType = cmStateEnums::STATIC_LIBRARY;
+ } else {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Invalid value '", *tt,
+ "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '",
+ cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE),
+ "' and '",
+ cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY),
+ "' are allowed."));
+ return false;
+ }
+ }
+
+ cmCoreTryCompile tc(&mf);
+ cmCoreTryCompile::Arguments arguments =
+ tc.ParseArgs(cmMakeRange(args), false);
+ if (!arguments) {
+ return true;
+ }
+ tc.TryCompileCode(arguments, targetType);
// if They specified clean then we clean up what we can
- if (this->SrcFileSignature) {
- if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
- this->CleanupFiles(this->BinaryDirectory);
+ if (tc.SrcFileSignature) {
+ if (!mf.GetCMakeInstance()->GetDebugTryCompile()) {
+ tc.CleanupFiles(tc.BinaryDirectory);
}
}
return true;
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index d8cc16e59..6a3430b6b 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -7,33 +7,7 @@
#include <string>
#include <vector>
-#include <cm/memory>
-
-#include "cmCommand.h"
-#include "cmCoreTryCompile.h"
-
class cmExecutionStatus;
-/** \class cmTryCompileCommand
- * \brief Specifies where to install some files
- *
- * cmTryCompileCommand is used to test if source code can be compiled
- */
-class cmTryCompileCommand : public cmCoreTryCompile
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- std::unique_ptr<cmCommand> Clone() override
- {
- return cm::make_unique<cmTryCompileCommand>();
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) override;
-};
+bool cmTryCompileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index c82ac6429..1e81195b8 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -4,9 +4,14 @@
#include <cstdio>
+#include <cm/optional>
+
#include "cmsys/FStream.hxx"
+#include "cmArgumentParserTypes.h"
+#include "cmCoreTryCompile.h"
#include "cmDuration.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
@@ -17,157 +22,157 @@
#include "cmValue.h"
#include "cmake.h"
-class cmExecutionStatus;
+namespace {
-// cmTryRunCommand
-bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
- cmExecutionStatus&)
+class TryRunCommandImpl : public cmCoreTryCompile
{
- if (argv.size() < 4) {
- return false;
- }
-
- if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
- cmake::FIND_PACKAGE_MODE) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "The try_run() command is not supported in --find-package mode.");
- return false;
+public:
+ TryRunCommandImpl(cmMakefile* mf)
+ : cmCoreTryCompile(mf)
+ {
}
- // build an arg list for TryCompile and extract the runArgs,
- std::vector<std::string> tryCompile;
-
- this->CompileResultVariable.clear();
- this->RunResultVariable.clear();
- this->OutputVariable.clear();
- this->RunOutputVariable.clear();
- this->CompileOutputVariable.clear();
-
- std::string runArgs;
- unsigned int i;
- for (i = 1; i < argv.size(); ++i) {
- if (argv[i] == "ARGS") {
- ++i;
- while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
- argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" &&
- argv[i] != "LINK_LIBRARIES") {
- runArgs += " ";
- runArgs += argv[i];
- ++i;
- }
- if (i < argv.size()) {
- tryCompile.push_back(argv[i]);
- }
- } else {
- if (argv[i] == "OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->OutputVariable = argv[i];
- } else if (argv[i] == "RUN_OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "RUN_OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->RunOutputVariable = argv[i];
- } else if (argv[i] == "COMPILE_OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "COMPILE_OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->CompileOutputVariable = argv[i];
- } else if (argv[i] == "WORKING_DIRECTORY") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "WORKING_DIRECTORY specified but there is no variable");
- return false;
- }
- i++;
- this->WorkingDirectory = argv[i];
- } else {
- tryCompile.push_back(argv[i]);
- }
- }
+ bool TryRunCode(std::vector<std::string> const& args);
+
+ void RunExecutable(const std::string& runArgs,
+ cm::optional<std::string> const& workDir,
+ std::string* runOutputContents,
+ std::string* runOutputStdOutContents,
+ std::string* runOutputStdErrContents);
+ void DoNotRunExecutable(const std::string& runArgs,
+ const std::string& srcFile,
+ std::string const& compileResultVariable,
+ std::string* runOutputContents,
+ std::string* runOutputStdOutContents,
+ std::string* runOutputStdErrContents);
+
+ bool NoCache;
+ std::string RunResultVariable;
+};
+
+bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
+{
+ this->RunResultVariable = argv[0];
+ cmCoreTryCompile::Arguments arguments =
+ this->ParseArgs(cmMakeRange(argv).advance(1), true);
+ if (!arguments) {
+ return true;
}
+ this->NoCache = arguments.NoCache;
// although they could be used together, don't allow it, because
// using OUTPUT_VARIABLE makes crosscompiling harder
- if (!this->OutputVariable.empty() &&
- (!this->RunOutputVariable.empty() ||
- !this->CompileOutputVariable.empty())) {
+ if (arguments.OutputVariable &&
+ (arguments.CompileOutputVariable || arguments.RunOutputVariable ||
+ arguments.RunOutputStdOutVariable ||
+ arguments.RunOutputStdErrVariable)) {
cmSystemTools::Error(
"You cannot use OUTPUT_VARIABLE together with COMPILE_OUTPUT_VARIABLE "
- "or RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE and/or "
- "RUN_OUTPUT_VARIABLE.");
+ ", RUN_OUTPUT_VARIABLE, RUN_OUTPUT_STDOUT_VARIABLE or "
+ "RUN_OUTPUT_STDERR_VARIABLE. "
+ "Please use only COMPILE_OUTPUT_VARIABLE, RUN_OUTPUT_VARIABLE, "
+ "RUN_OUTPUT_STDOUT_VARIABLE "
+ "and/or RUN_OUTPUT_STDERR_VARIABLE.");
+ return false;
+ }
+
+ if ((arguments.RunOutputStdOutVariable ||
+ arguments.RunOutputStdErrVariable) &&
+ arguments.RunOutputVariable) {
+ cmSystemTools::Error(
+ "You cannot use RUN_OUTPUT_STDOUT_VARIABLE or "
+ "RUN_OUTPUT_STDERR_VARIABLE together "
+ "with RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE or "
+ "RUN_OUTPUT_STDOUT_VARIABLE and/or RUN_OUTPUT_STDERR_VARIABLE.");
return false;
}
- if (!this->WorkingDirectory.empty()) {
- if (!cmSystemTools::MakeDirectory(this->WorkingDirectory)) {
+ if (arguments.RunWorkingDirectory) {
+ if (!cmSystemTools::MakeDirectory(*arguments.RunWorkingDirectory)) {
cmSystemTools::Error(cmStrCat("Error creating working directory \"",
- this->WorkingDirectory, "\"."));
+ *arguments.RunWorkingDirectory, "\"."));
return false;
}
}
bool captureRunOutput = false;
- if (!this->OutputVariable.empty()) {
+ bool captureRunOutputStdOutErr = false;
+ if (arguments.OutputVariable) {
captureRunOutput = true;
- tryCompile.emplace_back("OUTPUT_VARIABLE");
- tryCompile.push_back(this->OutputVariable);
+ } else if (arguments.CompileOutputVariable) {
+ arguments.OutputVariable = arguments.CompileOutputVariable;
}
- if (!this->CompileOutputVariable.empty()) {
- tryCompile.emplace_back("OUTPUT_VARIABLE");
- tryCompile.push_back(this->CompileOutputVariable);
- }
- if (!this->RunOutputVariable.empty()) {
+ if (arguments.RunOutputStdOutVariable || arguments.RunOutputStdErrVariable) {
+ captureRunOutputStdOutErr = true;
+ } else if (arguments.RunOutputVariable) {
captureRunOutput = true;
}
- this->RunResultVariable = argv[0];
- this->CompileResultVariable = argv[1];
-
// do the try compile
- int res = this->TryCompileCode(tryCompile, true);
+ bool compiled = this->TryCompileCode(arguments, cmStateEnums::EXECUTABLE);
// now try running the command if it compiled
- if (!res) {
+ if (compiled) {
if (this->OutputFile.empty()) {
cmSystemTools::Error(this->FindErrorMessage);
} else {
+ std::string runArgs;
+ if (arguments.RunArgs) {
+ runArgs = cmStrCat(" ", cmJoin(*arguments.RunArgs, " "));
+ }
+
// "run" it and capture the output
std::string runOutputContents;
+ std::string runOutputStdOutContents;
+ std::string runOutputStdErrContents;
if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") &&
!this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) {
this->DoNotRunExecutable(
- runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr);
+ runArgs, *arguments.SourceDirectoryOrFile,
+ *arguments.CompileResultVariable,
+ captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable
+ ? &runOutputStdOutContents
+ : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable
+ ? &runOutputStdErrContents
+ : nullptr);
} else {
- this->RunExecutable(runArgs, &runOutputContents);
+ this->RunExecutable(
+ runArgs, arguments.RunWorkingDirectory,
+ captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable
+ ? &runOutputStdOutContents
+ : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable
+ ? &runOutputStdErrContents
+ : nullptr);
}
// now put the output into the variables
- if (!this->RunOutputVariable.empty()) {
- this->Makefile->AddDefinition(this->RunOutputVariable,
+ if (arguments.RunOutputVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputVariable,
runOutputContents);
}
+ if (arguments.RunOutputStdOutVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputStdOutVariable,
+ runOutputStdOutContents);
+ }
+ if (arguments.RunOutputStdErrVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputStdErrVariable,
+ runOutputStdErrContents);
+ }
- if (!this->OutputVariable.empty()) {
+ if (arguments.OutputVariable && !arguments.CompileOutputVariable) {
// if the TryCompileCore saved output in this outputVariable then
// prepend that output to this output
cmValue compileOutput =
- this->Makefile->GetDefinition(this->OutputVariable);
+ this->Makefile->GetDefinition(*arguments.OutputVariable);
if (compileOutput) {
runOutputContents = *compileOutput + runOutputContents;
}
- this->Makefile->AddDefinition(this->OutputVariable, runOutputContents);
+ this->Makefile->AddDefinition(*arguments.OutputVariable,
+ runOutputContents);
}
}
}
@@ -179,8 +184,10 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
return true;
}
-void cmTryRunCommand::RunExecutable(const std::string& runArgs,
- std::string* out)
+void TryRunCommandImpl::RunExecutable(const std::string& runArgs,
+ cm::optional<std::string> const& workDir,
+ std::string* out, std::string* stdOut,
+ std::string* stdErr)
{
int retVal = -1;
@@ -204,9 +211,10 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
finalCommand += runArgs;
}
bool worked = cmSystemTools::RunSingleCommand(
- finalCommand, out, out, &retVal,
- this->WorkingDirectory.empty() ? nullptr : this->WorkingDirectory.c_str(),
- cmSystemTools::OUTPUT_NONE, cmDuration::zero());
+ finalCommand, stdOut || stdErr ? stdOut : out,
+ stdOut || stdErr ? stdErr : out, &retVal,
+ workDir ? workDir->c_str() : nullptr, cmSystemTools::OUTPUT_NONE,
+ cmDuration::zero());
// set the run var
char retChar[16];
const char* retStr;
@@ -216,18 +224,23 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
} else {
retStr = "FAILED_TO_RUN";
}
- this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr,
- "Result of try_run()",
- cmStateEnums::INTERNAL);
+ if (this->NoCache) {
+ this->Makefile->AddDefinition(this->RunResultVariable, retStr);
+ } else {
+ this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr,
+ "Result of try_run()",
+ cmStateEnums::INTERNAL);
+ }
}
/* This is only used when cross compiling. Instead of running the
executable, two cache variables are created which will hold the results
the executable would have produced.
*/
-void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
- const std::string& srcFile,
- std::string* out)
+void TryRunCommandImpl::DoNotRunExecutable(
+ const std::string& runArgs, const std::string& srcFile,
+ std::string const& compileResultVariable, std::string* out,
+ std::string* stdOut, std::string* stdErr)
{
// copy the executable out of the CMakeFiles/ directory, so it is not
// removed at the end of try_run() and the user can run it manually
@@ -246,6 +259,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
std::string internalRunOutputName =
this->RunResultVariable + "__TRYRUN_OUTPUT";
+ std::string internalRunOutputStdOutName =
+ this->RunResultVariable + "__TRYRUN_OUTPUT_STDOUT";
+ std::string internalRunOutputStdErrName =
+ this->RunResultVariable + "__TRYRUN_OUTPUT_STDERR";
bool error = false;
if (!this->Makefile->GetDefinition(this->RunResultVariable)) {
@@ -269,7 +286,51 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
}
// is the output from the executable used ?
- if (out) {
+ if (stdOut || stdErr) {
+ if (!this->Makefile->GetDefinition(internalRunOutputStdOutName)) {
+ // if the variables doesn't exist, create it with a helpful error text
+ // and mark it as advanced
+ std::string comment = cmStrCat(
+ "Output of try_run(), contains the text, which the executable "
+ "would have printed on stdout on its target platform.\n",
+ detailsString);
+
+ this->Makefile->AddCacheDefinition(
+ internalRunOutputStdOutName, "PLEASE_FILL_OUT-NOTFOUND",
+ comment.c_str(), cmStateEnums::STRING);
+ cmState* state = this->Makefile->GetState();
+ cmValue existing =
+ state->GetCacheEntryValue(internalRunOutputStdOutName);
+ if (existing) {
+ state->SetCacheEntryProperty(internalRunOutputStdOutName, "ADVANCED",
+ "1");
+ }
+
+ error = true;
+ }
+
+ if (!this->Makefile->GetDefinition(internalRunOutputStdErrName)) {
+ // if the variables doesn't exist, create it with a helpful error text
+ // and mark it as advanced
+ std::string comment = cmStrCat(
+ "Output of try_run(), contains the text, which the executable "
+ "would have printed on stderr on its target platform.\n",
+ detailsString);
+
+ this->Makefile->AddCacheDefinition(
+ internalRunOutputStdErrName, "PLEASE_FILL_OUT-NOTFOUND",
+ comment.c_str(), cmStateEnums::STRING);
+ cmState* state = this->Makefile->GetState();
+ cmValue existing =
+ state->GetCacheEntryValue(internalRunOutputStdErrName);
+ if (existing) {
+ state->SetCacheEntryProperty(internalRunOutputStdErrName, "ADVANCED",
+ "1");
+ }
+
+ error = true;
+ }
+ } else if (out) {
if (!this->Makefile->GetDefinition(internalRunOutputName)) {
// if the variables doesn't exist, create it with a helpful error text
// and mark it as advanced
@@ -317,7 +378,34 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
" to\n"
" the exit code (in many cases 0 for success), otherwise "
"enter \"FAILED_TO_RUN\".\n");
- if (out) {
+ if (stdOut || stdErr) {
+ if (stdOut) {
+ comment += internalRunOutputStdOutName;
+ comment +=
+ "\n contains the text the executable "
+ "would have printed on stdout.\n"
+ " If the executable would not have been able to run, set ";
+ comment += internalRunOutputStdOutName;
+ comment += " empty.\n"
+ " Otherwise check if the output is evaluated by the "
+ "calling CMake code. If so,\n"
+ " check what the source file would have printed when "
+ "called with the given arguments.\n";
+ }
+ if (stdErr) {
+ comment += internalRunOutputStdErrName;
+ comment +=
+ "\n contains the text the executable "
+ "would have printed on stderr.\n"
+ " If the executable would not have been able to run, set ";
+ comment += internalRunOutputStdErrName;
+ comment += " empty.\n"
+ " Otherwise check if the output is evaluated by the "
+ "calling CMake code. If so,\n"
+ " check what the source file would have printed when "
+ "called with the given arguments.\n";
+ }
+ } else if (out) {
comment += internalRunOutputName;
comment +=
"\n contains the text the executable "
@@ -330,8 +418,9 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
" check what the source file would have printed when "
"called with the given arguments.\n";
}
+
comment += "The ";
- comment += this->CompileResultVariable;
+ comment += compileResultVariable;
comment += " variable holds the build result for this try_run().\n\n"
"Source file : ";
comment += srcFile + "\n";
@@ -370,7 +459,37 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
return;
}
- if (out) {
+ if (stdOut || stdErr) {
+ if (stdOut) {
+ (*stdOut) = *this->Makefile->GetDefinition(internalRunOutputStdOutName);
+ }
+ if (stdErr) {
+ (*stdErr) = *this->Makefile->GetDefinition(internalRunOutputStdErrName);
+ }
+ } else if (out) {
(*out) = *this->Makefile->GetDefinition(internalRunOutputName);
}
}
+}
+
+bool cmTryRunCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+
+ if (args.size() < 4) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "The try_run() command requires at least 4 arguments.");
+ return false;
+ }
+
+ if (mf.GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The try_run() command is not supported in --find-package mode.");
+ return false;
+ }
+
+ TryRunCommandImpl tr(&mf);
+ return tr.TryRunCode(args);
+}
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index d45acd85e..38e36380e 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -7,47 +7,7 @@
#include <string>
#include <vector>
-#include <cm/memory>
-
-#include "cmCommand.h"
-#include "cmCoreTryCompile.h"
-
class cmExecutionStatus;
-/** \class cmTryRunCommand
- * \brief Specifies where to install some files
- *
- * cmTryRunCommand is used to test if source code can be compiled
- */
-class cmTryRunCommand : public cmCoreTryCompile
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- std::unique_ptr<cmCommand> Clone() override
- {
- return cm::make_unique<cmTryRunCommand>();
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) override;
-
-private:
- void RunExecutable(const std::string& runArgs,
- std::string* runOutputContents);
- void DoNotRunExecutable(const std::string& runArgs,
- const std::string& srcFile,
- std::string* runOutputContents);
-
- std::string CompileResultVariable;
- std::string RunResultVariable;
- std::string OutputVariable;
- std::string RunOutputVariable;
- std::string CompileOutputVariable;
- std::string WorkingDirectory;
-};
+bool cmTryRunCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 9f3d62033..4cfb561b5 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -354,6 +354,18 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
void cmVisualStudio10TargetGenerator::Generate()
{
+ for (std::string const& config : this->Configurations) {
+ this->GeneratorTarget->CheckCxxModuleStatus(config);
+ }
+
+ if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GeneratorTarget->GetName(),
+ "\" target contains C++ module sources which are not supported "
+ "by the generator"));
+ }
+
this->ProjectType = computeProjectType(this->GeneratorTarget);
this->Managed = this->ProjectType == VsProjectType::csproj;
const std::string ProjectFileExtension =
@@ -483,7 +495,7 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
e1.Element("PreferredToolArchitecture", hostArch);
}
- // ALL_BUILD and ZERO_CHECK projects transitively include
+ // The ALL_BUILD, PACKAGE, and ZERO_CHECK projects transitively include
// Microsoft.Common.CurrentVersion.targets which triggers Target
// ResolveNugetPackageAssets when SDK-style targets are in the project.
// However, these projects have no nuget packages to reference and the
@@ -491,7 +503,7 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
// Setting ResolveNugetPackages to false skips this target and the build
// succeeds.
cm::string_view targetName{ this->GeneratorTarget->GetName() };
- if (targetName == "ALL_BUILD" ||
+ if (targetName == "ALL_BUILD" || targetName == "PACKAGE" ||
targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
Elem e1(e0, "PropertyGroup");
e1.Element("ResolveNugetPackages", "false");
@@ -899,9 +911,11 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
e1.Element("TargetFrameworks", *targetFramework);
} else {
e1.Element("TargetFramework", *targetFramework);
+ e1.Element("AppendTargetFrameworkToOutputPath", "false");
}
} else {
e1.Element("TargetFramework", "net5.0");
+ e1.Element("AppendTargetFrameworkToOutputPath", "false");
}
std::string outputType;
@@ -957,6 +971,10 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
ConvertToWindowsSlash(outDir);
e1.Element("OutputPath", outDir);
+
+ Options& o = *(this->ClOptions[config]);
+ OptionsHelper oh(o, e1);
+ oh.OutputFlagMap();
}
this->WriteDotNetDocumentationFile(e0);
@@ -1507,6 +1525,10 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
this->ASanEnabledConfigurations.end()) {
e1.Element("EnableAsan", "true");
}
+ if (this->FuzzerEnabledConfigurations.find(config) !=
+ this->FuzzerEnabledConfigurations.end()) {
+ e1.Element("EnableFuzzer", "true");
+ }
{
auto s = this->SpectreMitigation.find(config);
if (s != this->SpectreMitigation.end()) {
@@ -1788,11 +1810,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
e2.WritePlatformConfigTag("Command", cond, script);
e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
e2.WritePlatformConfigTag("Outputs", cond, outputs);
- if (this->LocalGenerator->GetVersion() >
- cmGlobalVisualStudioGenerator::VSVersion::VS10) {
- // VS >= 11 let us turn off linking of custom command outputs.
- e2.WritePlatformConfigTag("LinkObjects", cond, "false");
- }
+ // Turn off linking of custom command outputs.
+ e2.WritePlatformConfigTag("LinkObjects", cond, "false");
if (symbolic &&
this->LocalGenerator->GetVersion() >=
cmGlobalVisualStudioGenerator::VSVersion::VS16) {
@@ -2357,28 +2376,6 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
// we must use relative paths.
bool forceRelative = sf->GetLanguage() == "CUDA";
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
- if (this->LocalGenerator->GetVersion() ==
- cmGlobalVisualStudioGenerator::VSVersion::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile)) {
- // Normal path conversion resulted in a full path. VS 10 (but not 11)
- // refuses to show the property page in the IDE for a source file with a
- // full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
- // relative path but to allow deeper build trees CMake 2.8.[5678] used a
- // full path except for custom commands. Custom commands do not work
- // without a relative path, but they do not seem to be involved in tools
- // with the above behavior. For other sources we now use a relative path
- // when the combined path will not be too long so property pages appear.
- std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
- size_t const maxLen = 250;
- if (sf->GetCustomCommand() ||
- ((this->LocalGenerator->GetCurrentBinaryDirectory().length() + 1 +
- sourceRel.length()) <= maxLen)) {
- forceRelative = true;
- sourceFile = sourceRel;
- } else {
- this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
- }
- }
ConvertToWindowsSlash(sourceFile);
e2.Attribute("Include", sourceFile);
@@ -2875,7 +2872,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
Elem& e0)
{
cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
- if (ttype > cmStateEnums::GLOBAL_TARGET) {
+ if (ttype > cmStateEnums::INTERFACE_LIBRARY) {
return;
}
if (this->ProjectType == VsProjectType::csproj) {
@@ -3117,6 +3114,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->LangForClCompile = langForClCompile;
if (!langForClCompile.empty()) {
this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+ cmBuildStep::Compile,
langForClCompile, configName);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
@@ -3128,10 +3126,17 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
// Check if ASan is enabled.
- if (flags.find("/fsanitize=address") != std::string::npos) {
+ if (flags.find("/fsanitize=address") != std::string::npos ||
+ flags.find("-fsanitize=address") != std::string::npos) {
this->ASanEnabledConfigurations.insert(configName);
}
+ // Check if (lib)Fuzzer is enabled.
+ if (flags.find("/fsanitize=fuzzer") != std::string::npos ||
+ flags.find("-fsanitize=fuzzer") != std::string::npos) {
+ this->FuzzerEnabledConfigurations.insert(configName);
+ }
+
// Precompile Headers
std::string pchHeader =
this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
@@ -3173,7 +3178,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// anymore, because cmGeneratorTarget may not be aware that the
// target uses C++/CLI.
if (flags.find("/clr") != std::string::npos ||
- defineFlags.find("/clr") != std::string::npos) {
+ flags.find("-clr") != std::string::npos ||
+ defineFlags.find("/clr") != std::string::npos ||
+ defineFlags.find("-clr") != std::string::npos) {
if (configName == this->Configurations[0]) {
std::string message = "For the target \"" +
this->GeneratorTarget->GetName() +
@@ -3492,8 +3499,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
// Get compile flags for CUDA in this directory.
std::string flags;
- this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, "CUDA",
- configName);
+ this->LocalGenerator->AddLanguageFlags(
+ flags, this->GeneratorTarget, cmBuildStep::Compile, "CUDA", configName);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
configName);
@@ -3685,21 +3692,28 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
this->GeneratorTarget->GetLinkOptions(linkOpts, configName, "CUDA");
// LINK_OPTIONS are escaped.
this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts);
+
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(configName);
+ if (doDeviceLinking && pcli) {
+
+ cmLinkLineDeviceComputer computer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory());
+ std::string ignored_;
+ this->LocalGenerator->GetDeviceLinkFlags(computer, configName, ignored_,
+ linkFlags, ignored_, ignored_,
+ this->GeneratorTarget);
+
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ linkFlags, this->GeneratorTarget, "CUDA", configName);
+ }
cudaLinkOptions.AppendFlagString("AdditionalOptions", linkFlags);
// For static libraries that have device linking enabled compute
// the libraries
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY &&
doDeviceLinking) {
- cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(configName);
- if (!pcli) {
- cmSystemTools::Error(
- "CMake can not compute cmComputeLinkInformation for target: " +
- this->Name);
- return false;
- }
-
cmComputeLinkInformation& cli = *pcli;
cmLinkLineDeviceComputer computer(
this->LocalGenerator,
@@ -3757,7 +3771,8 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string flags;
this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
- "ASM_MASM", configName);
+ cmBuildStep::Compile, "ASM_MASM",
+ configName);
masmOptions.Parse(flags);
@@ -3809,7 +3824,8 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string flags;
this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
- "ASM_NASM", configName);
+ cmBuildStep::Compile, "ASM_NASM",
+ configName);
flags += " -f";
flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT");
nasmOptions.Parse(flags);
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 8d777a33a..17dcecdb1 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -231,6 +231,7 @@ private:
bool TargetCompileAsWinRT;
std::set<std::string> IPOEnabledConfigurations;
std::set<std::string> ASanEnabledConfigurations;
+ std::set<std::string> FuzzerEnabledConfigurations;
std::map<std::string, std::string> SpectreMitigation;
cmGlobalVisualStudio10Generator* const GlobalGenerator;
cmLocalVisualStudio10Generator* const LocalGenerator;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 00c65edd7..e6f5ece39 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -75,7 +75,6 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
// the flag to disable exception handling. When the user does
// remove the flag we need to override the IDE default of on.
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VSVersion::VS10:
case cmGlobalVisualStudioGenerator::VSVersion::VS11:
case cmGlobalVisualStudioGenerator::VSVersion::VS12:
case cmGlobalVisualStudioGenerator::VSVersion::VS14:
@@ -101,14 +100,12 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
// to the generated project to disable logo suppression. Otherwise
// the GUI default is to enable suppression.
//
- // On Visual Studio 10 (and later!), the value of this attribute should be
- // an empty string, instead of "FALSE", in order to avoid a warning:
- // "cl ... warning D9035: option 'nologo-' has been deprecated"
- //
+ // On Visual Studio 9, the value of this attribute should be
+ // "FALSE", instead of an empty string.
if (verbose &&
this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end()) {
this->FlagMap["SuppressStartupBanner"] =
- this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10 ? "FALSE"
+ this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS9 ? "FALSE"
: "";
}
}
@@ -161,71 +158,12 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const
void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
{
- // Extract temporary values stored by our flag table.
- FlagValue arch = this->TakeFlag("cmake-temp-arch");
- FlagValue code = this->TakeFlag("cmake-temp-code");
- FlagValue gencode = this->TakeFlag("cmake-temp-gencode");
-
- // No -code allowed without -arch.
- if (arch.empty()) {
- code.clear();
- }
-
- // Create a CodeGeneration field with [arch],[code] syntax in each entry.
- // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
- FlagValue& result = this->FlagMap["CodeGeneration"];
-
- // If there are no flags, leave the CodeGeneration field empty.
- if (arch.empty() && gencode.empty()) {
- return;
- }
-
- // First entries for the -arch=<arch> [-code=<code>,...] pair.
- if (!arch.empty()) {
- std::string arch_name = arch[0];
- if (arch_name == "all" || arch_name == "all-major" ||
- arch_name == "native") {
- AppendFlagString("AdditionalOptions", "-arch=" + arch_name);
- return;
- }
- std::vector<std::string> codes;
- if (!code.empty()) {
- codes = cmTokenize(code[0], ",");
- }
- if (codes.empty()) {
- codes.push_back(arch_name);
- // nvcc -arch=<arch> has a special case that allows a real
- // architecture to be specified instead of a virtual arch.
- // It translates to -arch=<virtual> -code=<real>.
- cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
- }
- for (std::string const& c : codes) {
- std::string entry = arch_name + "," + c;
- result.push_back(entry);
- }
- }
-
- // Now add entries for the following signatures:
- // -gencode=<arch>,<code>
- // -gencode=<arch>,[<code1>,<code2>]
- // -gencode=<arch>,"<code1>,<code2>"
- for (std::string const& e : gencode) {
- std::string entry = e;
- cmSystemTools::ReplaceString(entry, "arch=", "");
- cmSystemTools::ReplaceString(entry, "code=", "");
- cmSystemTools::ReplaceString(entry, "[", "");
- cmSystemTools::ReplaceString(entry, "]", "");
- cmSystemTools::ReplaceString(entry, "\"", "");
-
- std::vector<std::string> codes = cmTokenize(entry, ",");
- if (codes.size() >= 2) {
- auto gencode_arch = cm::cbegin(codes);
- for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) {
- std::string code_entry = *gencode_arch + "," + *ci;
- result.push_back(code_entry);
- }
- }
- }
+ // Create an empty CodeGeneration field, and pass the the actual
+ // compile flags via additional options so that we have consistent
+ // behavior and avoid issues with MSBuild extensions injecting
+ // virtual code when we request real only.
+ FlagValue& code_gen_flag = this->FlagMap["CodeGeneration"];
+ code_gen_flag = "";
}
void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
@@ -432,7 +370,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
std::ostringstream oss;
- if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) {
oss << "%(" << tag << ")";
}
std::vector<std::string>::const_iterator de =
@@ -440,13 +378,13 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) {
// Escape the definition for the compiler.
std::string define;
- if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS9) {
define = this->LocalGenerator->EscapeForShell(di, true);
} else {
define = di;
}
// Escape this flag for the MSBuild.
- if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) {
cmVS10EscapeForMSBuild(define);
if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
@@ -488,7 +426,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
}
// Escape this include for the MSBuild.
- if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) {
cmVS10EscapeForMSBuild(include);
}
oss << sep << include;
@@ -500,7 +438,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
}
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) {
oss << sep << "%(" << tag << ")";
}
@@ -514,7 +452,7 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
std::ostringstream oss;
const char* sep = "";
for (std::string i : m.second) {
- if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) {
cmVS10EscapeForMSBuild(i);
}
oss << sep << i;
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index fb9427398..e80d1fcf0 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -96,7 +96,7 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus status(mf);
mf.ExecuteCommand(fn, status);
if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
+ inStatus.SetReturnInvoked(status.GetReturnVariables());
return true;
}
if (status.GetBreakInvoked()) {
diff --git a/Source/cmWindowsRegistry.h b/Source/cmWindowsRegistry.h
index 2eed2977f..f4a0e7b82 100644
--- a/Source/cmWindowsRegistry.h
+++ b/Source/cmWindowsRegistry.h
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include <cstdint> // IWYU pragma: keep
#include <string>
#include <vector>
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index adc500a07..e727d2214 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -67,9 +67,14 @@ void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
xout.Attribute("LastUpgradeVersion", WriteVersionString());
xout.Attribute("version", "1.3");
+ cmValue propDftCfg =
+ Target->GetTarget()->GetProperty("XCODE_SCHEME_LAUNCH_CONFIGURATION");
+ std::string launchConfiguration =
+ !propDftCfg.IsEmpty() ? *propDftCfg : "Debug";
+
WriteBuildAction(xout, container);
WriteTestAction(xout, FindConfiguration("Debug"), container);
- WriteLaunchAction(xout, FindConfiguration("Debug"), container);
+ WriteLaunchAction(xout, FindConfiguration(launchConfiguration), container);
WriteProfileAction(xout, FindConfiguration("Release"));
WriteAnalyzeAction(xout, FindConfiguration("Debug"));
WriteArchiveAction(xout, FindConfiguration("Release"));
@@ -147,7 +152,15 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
"Xcode.DebuggerFoundation.Debugger.LLDB");
xout.Attribute("selectedLauncherIdentifier",
"Xcode.DebuggerFoundation.Launcher.LLDB");
- xout.Attribute("launchStyle", "0");
+ {
+ cmValue launchMode =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_LAUNCH_MODE");
+ std::string value = "0"; // == 'AUTO'
+ if (launchMode && *launchMode == "WAIT") {
+ value = "1";
+ }
+ xout.Attribute("launchStyle", value);
+ }
WriteCustomWorkingDirectory(xout, configuration);
xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
@@ -190,6 +203,23 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
WriteLaunchActionAttribute(xout, "enableUBSanitizer",
"XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
+
+ if (cmValue value = this->Target->GetTarget()->GetProperty(
+ "XCODE_SCHEME_ENABLE_GPU_API_VALIDATION")) {
+ if (value.IsOff()) {
+ xout.Attribute("enableGPUValidationMode",
+ "1"); // unset means YES, "1" means NO
+ }
+ }
+
+ if (cmValue value = this->Target->GetTarget()->GetProperty(
+ "XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION")) {
+ if (value.IsOn()) {
+ xout.Attribute("enableGPUShaderValidationMode",
+ "2"); // unset means NO, "2" means YES
+ }
+ }
+
WriteLaunchActionAttribute(
xout, "stopOnEveryUBSanitizerIssue",
"XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index 8115306d7..2d2a377ec 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -19,6 +19,12 @@ codecvt::codecvt(Encoding e)
#endif
{
switch (e) {
+ case codecvt::ConsoleOutput:
+#if defined(_WIN32)
+ m_noconv = false;
+ m_codepage = GetConsoleOutputCP();
+ break;
+#endif
case codecvt::ANSI:
#if defined(_WIN32)
m_noconv = false;
diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx
index 9af083fee..f628de718 100644
--- a/Source/cm_codecvt.hxx
+++ b/Source/cm_codecvt.hxx
@@ -15,7 +15,8 @@ public:
None,
UTF8,
UTF8_WITH_BOM,
- ANSI
+ ANSI,
+ ConsoleOutput,
};
#ifndef CMAKE_BOOTSTRAP
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 1c1cab37f..013a87b51 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -3,6 +3,7 @@
#include "cmake.h"
#include <algorithm>
+#include <array>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -22,6 +23,10 @@
#include <cmext/algorithm>
#include <cmext/string_view>
+#if !defined(CMAKE_BOOTSTRAP) && !defined(_WIN32)
+# include <unistd.h>
+#endif
+
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -55,6 +60,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
+#include "cmUVProcessChain.h"
#include "cmUtils.hxx"
#include "cmVersionConfig.h"
#include "cmWorkingDirectory.h"
@@ -62,6 +68,7 @@
#if !defined(CMAKE_BOOTSTRAP)
# include <unordered_map>
+# include <cm3p/curl/curl.h>
# include <cm3p/json/writer.h>
# include "cmFileAPI.h"
@@ -81,7 +88,6 @@
# include "cmGlobalBorlandMakefileGenerator.h"
# include "cmGlobalJOMMakefileGenerator.h"
# include "cmGlobalNMakeMakefileGenerator.h"
-# include "cmGlobalVisualStudio10Generator.h"
# include "cmGlobalVisualStudio11Generator.h"
# include "cmGlobalVisualStudio12Generator.h"
# include "cmGlobalVisualStudio14Generator.h"
@@ -251,6 +257,8 @@ Json::Value cmake::ReportCapabilitiesJson() const
std::vector<cmake::GeneratorInfo> generatorInfoList;
this->GetRegisteredGenerators(generatorInfoList);
+ auto* curlVersion = curl_version_info(CURLVERSION_FIRST);
+
JsonValueMapType generatorMap;
for (cmake::GeneratorInfo const& gi : generatorInfoList) {
if (gi.isAlias) { // skip aliases, they are there for compatibility reasons
@@ -285,6 +293,7 @@ Json::Value cmake::ReportCapabilitiesJson() const
obj["generators"] = generators;
obj["fileApi"] = cmFileAPI::ReportCapabilities();
obj["serverMode"] = false;
+ obj["tls"] = static_cast<bool>(curlVersion->features & CURL_VERSION_SSL);
return obj;
}
@@ -777,6 +786,8 @@ enum class ListPresets
Configure,
Build,
Test,
+ Package,
+ Workflow,
All,
};
}
@@ -951,7 +962,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
const auto logLevel = StringToLogLevel(value);
- if (logLevel == LogLevel::LOG_UNDEFINED) {
+ if (logLevel == Message::LogLevel::LOG_UNDEFINED) {
cmSystemTools::Error(
"Invalid level specified for --log-level");
return false;
@@ -967,7 +978,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
const auto logLevel = StringToLogLevel(value);
- if (logLevel == LogLevel::LOG_UNDEFINED) {
+ if (logLevel == Message::LogLevel::LOG_UNDEFINED) {
cmSystemTools::Error(
"Invalid level specified for --loglevel");
return false;
@@ -1132,12 +1143,16 @@ void cmake::SetArgs(const std::vector<std::string>& args)
listPresets = ListPresets::Build;
} else if (value == "test") {
listPresets = ListPresets::Test;
+ } else if (value == "package") {
+ listPresets = ListPresets::Package;
+ } else if (value == "workflow") {
+ listPresets = ListPresets::Workflow;
} else if (value == "all") {
listPresets = ListPresets::All;
} else {
cmSystemTools::Error(
"Invalid value specified for --list-presets.\n"
- "Valid values are configure, build, test, or all. "
+ "Valid values are configure, build, test, package, or all. "
"When no value is passed the default is configure.");
return false;
}
@@ -1282,9 +1297,13 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmCMakePresetsGraph presetsGraph;
auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory());
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
- cmSystemTools::Error(
+ std::string errorMsg =
cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
- ": ", cmCMakePresetsGraph::ResultToString(result)));
+ ": ", cmCMakePresetsGraph::ResultToString(result));
+ if (!presetsGraph.errors.empty()) {
+ errorMsg = cmStrCat(errorMsg, "\nErrors:\n", presetsGraph.errors);
+ }
+ cmSystemTools::Error(errorMsg);
return;
}
@@ -1295,6 +1314,10 @@ void cmake::SetArgs(const std::vector<std::string>& args)
presetsGraph.PrintBuildPresetList();
} else if (listPresets == ListPresets::Test) {
presetsGraph.PrintTestPresetList();
+ } else if (listPresets == ListPresets::Package) {
+ presetsGraph.PrintPackagePresetList();
+ } else if (listPresets == ListPresets::Workflow) {
+ presetsGraph.PrintWorkflowPresetList();
} else if (listPresets == ListPresets::All) {
presetsGraph.PrintAllPresets();
}
@@ -1398,23 +1421,52 @@ void cmake::SetArgs(const std::vector<std::string>& args)
#endif
}
-cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
-{
- using LevelsPair = std::pair<std::string, LogLevel>;
- static const std::vector<LevelsPair> levels = {
- { "error", LogLevel::LOG_ERROR }, { "warning", LogLevel::LOG_WARNING },
- { "notice", LogLevel::LOG_NOTICE }, { "status", LogLevel::LOG_STATUS },
- { "verbose", LogLevel::LOG_VERBOSE }, { "debug", LogLevel::LOG_DEBUG },
- { "trace", LogLevel::LOG_TRACE }
+namespace {
+using LevelsPair = std::pair<cm::string_view, Message::LogLevel>;
+using LevelsPairArray = std::array<LevelsPair, 7>;
+const LevelsPairArray& getStringToLogLevelPairs()
+{
+ static const LevelsPairArray levels = {
+ { { "error", Message::LogLevel::LOG_ERROR },
+ { "warning", Message::LogLevel::LOG_WARNING },
+ { "notice", Message::LogLevel::LOG_NOTICE },
+ { "status", Message::LogLevel::LOG_STATUS },
+ { "verbose", Message::LogLevel::LOG_VERBOSE },
+ { "debug", Message::LogLevel::LOG_DEBUG },
+ { "trace", Message::LogLevel::LOG_TRACE } }
};
+ return levels;
+}
+} // namespace
- const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr);
+Message::LogLevel cmake::StringToLogLevel(cm::string_view levelStr)
+{
+ const LevelsPairArray& levels = getStringToLogLevelPairs();
+
+ const auto levelStrLowCase =
+ cmSystemTools::LowerCase(std::string{ levelStr });
+ // NOLINTNEXTLINE(readability-qualified-auto)
const auto it = std::find_if(levels.cbegin(), levels.cend(),
[&levelStrLowCase](const LevelsPair& p) {
return p.first == levelStrLowCase;
});
- return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED;
+ return (it != levels.cend()) ? it->second : Message::LogLevel::LOG_UNDEFINED;
+}
+
+std::string cmake::LogLevelToString(Message::LogLevel level)
+{
+ const LevelsPairArray& levels = getStringToLogLevelPairs();
+
+ // NOLINTNEXTLINE(readability-qualified-auto)
+ const auto it =
+ std::find_if(levels.cbegin(), levels.cend(),
+ [&level](const LevelsPair& p) { return p.second == level; });
+ const cm::string_view levelStrLowerCase =
+ (it != levels.cend()) ? it->first : "undefined";
+ std::string levelStrUpperCase =
+ cmSystemTools::UpperCase(std::string{ levelStrLowerCase });
+ return levelStrUpperCase;
}
cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr)
@@ -2096,6 +2148,9 @@ int cmake::ActualConfigure()
this->UpdateConversionPathTable();
this->CleanupCommandsAndMacros();
+ cmSystemTools::RemoveADirectory(this->GetHomeOutputDirectory() +
+ "/CMakeFiles/CMakeScratch");
+
int res = this->DoPreConfigureChecks();
if (res < 0) {
return -2;
@@ -2319,7 +2374,6 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
{ "14.0", "Visual Studio 14 2015" }, //
{ "12.0", "Visual Studio 12 2013" }, //
{ "11.0", "Visual Studio 11 2012" }, //
- { "10.0", "Visual Studio 10 2010" }, //
{ "9.0", "Visual Studio 9 2008" }
};
static const char* const vsEntries[] = {
@@ -2648,7 +2702,6 @@ void cmake::AddDefaultGenerators()
this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory());
- this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory());
this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory());
@@ -3619,6 +3672,214 @@ bool cmake::Open(const std::string& dir, bool dryRun)
return gen->Open(dir, *cachedProjectName, dryRun);
}
+#if !defined(CMAKE_BOOTSTRAP)
+template <typename T>
+const T* cmake::FindPresetForWorkflow(
+ cm::static_string_view type,
+ const std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
+ const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step)
+{
+ auto it = presets.find(step.PresetName);
+ if (it == presets.end()) {
+ cmSystemTools::Error(cmStrCat("No such ", type, " preset in ",
+ this->GetHomeDirectory(), ": \"",
+ step.PresetName, '"'));
+ return nullptr;
+ }
+
+ if (it->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden ", type, " preset in ",
+ this->GetHomeDirectory(), ": \"",
+ step.PresetName, '"'));
+ return nullptr;
+ }
+
+ if (!it->second.Expanded) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate ", type, " preset \"",
+ step.PresetName,
+ "\": Invalid macro expansion"));
+ return nullptr;
+ }
+
+ if (!it->second.Expanded->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled ", type, " preset in ",
+ this->GetHomeDirectory(), ": \"",
+ step.PresetName, '"'));
+ return nullptr;
+ }
+
+ return &*it->second.Expanded;
+}
+
+std::function<int()> cmake::BuildWorkflowStep(
+ const std::vector<std::string>& args)
+{
+ cmUVProcessChainBuilder builder;
+ builder
+ .AddCommand(args)
+# ifdef _WIN32
+ .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, _fileno(stdout))
+ .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, _fileno(stderr));
+# else
+ .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, STDOUT_FILENO)
+ .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, STDERR_FILENO);
+# endif
+ return [builder]() -> int {
+ auto chain = builder.Start();
+ chain.Wait();
+ return static_cast<int>(chain.GetStatus().front()->ExitStatus);
+ };
+}
+#endif
+
+int cmake::Workflow(const std::string& presetName,
+ WorkflowListPresets listPresets, WorkflowFresh fresh)
+{
+#ifndef CMAKE_BOOTSTRAP
+ this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+
+ cmCMakePresetsGraph settingsFile;
+ auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
+ if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
+ cmSystemTools::Error(
+ cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ": ",
+ cmCMakePresetsGraph::ResultToString(result)));
+ return 1;
+ }
+
+ if (listPresets == WorkflowListPresets::Yes) {
+ settingsFile.PrintWorkflowPresetList();
+ return 0;
+ }
+
+ auto presetPair = settingsFile.WorkflowPresets.find(presetName);
+ if (presetPair == settingsFile.WorkflowPresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such workflow preset in ",
+ this->GetHomeDirectory(), ": \"", presetName,
+ '"'));
+ settingsFile.PrintWorkflowPresetList();
+ return 1;
+ }
+
+ if (presetPair->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden workflow preset in ",
+ this->GetHomeDirectory(), ": \"", presetName,
+ '"'));
+ settingsFile.PrintWorkflowPresetList();
+ return 1;
+ }
+
+ auto const& expandedPreset = presetPair->second.Expanded;
+ if (!expandedPreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate workflow preset \"",
+ presetName, "\": Invalid macro expansion"));
+ settingsFile.PrintWorkflowPresetList();
+ return 1;
+ }
+
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled workflow preset in ",
+ this->GetHomeDirectory(), ": \"", presetName,
+ '"'));
+ settingsFile.PrintWorkflowPresetList();
+ return 1;
+ }
+
+ struct CalculatedStep
+ {
+ int StepNumber;
+ cm::static_string_view Type;
+ std::string Name;
+ std::function<int()> Action;
+
+ CalculatedStep(int stepNumber, cm::static_string_view type,
+ std::string name, std::function<int()> action)
+ : StepNumber(stepNumber)
+ , Type(type)
+ , Name(std::move(name))
+ , Action(std::move(action))
+ {
+ }
+ };
+
+ std::vector<CalculatedStep> steps;
+ steps.reserve(expandedPreset->Steps.size());
+ int stepNumber = 1;
+ for (auto const& step : expandedPreset->Steps) {
+ switch (step.PresetType) {
+ case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::
+ Configure: {
+ auto const* configurePreset = this->FindPresetForWorkflow(
+ "configure"_s, settingsFile.ConfigurePresets, step);
+ if (!configurePreset) {
+ return 1;
+ }
+ std::vector<std::string> args{ cmSystemTools::GetCMakeCommand(),
+ "--preset", step.PresetName };
+ if (fresh == WorkflowFresh::Yes) {
+ args.emplace_back("--fresh");
+ }
+ steps.emplace_back(stepNumber, "configure"_s, step.PresetName,
+ this->BuildWorkflowStep(args));
+ } break;
+ case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Build: {
+ auto const* buildPreset = this->FindPresetForWorkflow(
+ "build"_s, settingsFile.BuildPresets, step);
+ if (!buildPreset) {
+ return 1;
+ }
+ steps.emplace_back(
+ stepNumber, "build"_s, step.PresetName,
+ this->BuildWorkflowStep({ cmSystemTools::GetCMakeCommand(),
+ "--build", "--preset", step.PresetName }));
+ } break;
+ case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Test: {
+ auto const* testPreset = this->FindPresetForWorkflow(
+ "test"_s, settingsFile.TestPresets, step);
+ if (!testPreset) {
+ return 1;
+ }
+ steps.emplace_back(
+ stepNumber, "test"_s, step.PresetName,
+ this->BuildWorkflowStep({ cmSystemTools::GetCTestCommand(),
+ "--preset", step.PresetName }));
+ } break;
+ case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Package: {
+ auto const* packagePreset = this->FindPresetForWorkflow(
+ "package"_s, settingsFile.PackagePresets, step);
+ if (!packagePreset) {
+ return 1;
+ }
+ steps.emplace_back(
+ stepNumber, "package"_s, step.PresetName,
+ this->BuildWorkflowStep({ cmSystemTools::GetCPackCommand(),
+ "--preset", step.PresetName }));
+ } break;
+ }
+ stepNumber++;
+ }
+
+ int stepResult;
+ bool first = true;
+ for (auto const& step : steps) {
+ if (!first) {
+ std::cout << "\n";
+ }
+ std::cout << "Executing workflow step " << step.StepNumber << " of "
+ << steps.size() << ": " << step.Type << " preset \"" << step.Name
+ << "\"\n\n"
+ << std::flush;
+ if ((stepResult = step.Action()) != 0) {
+ return stepResult;
+ }
+ first = false;
+ }
+#endif
+
+ return 0;
+}
+
void cmake::WatchUnusedCli(const std::string& var)
{
#ifndef CMAKE_BOOTSTRAP
diff --git a/Source/cmake.h b/Source/cmake.h
index 3c6af17b7..318357713 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -16,6 +16,7 @@
#include <vector>
#include <cm/string_view>
+#include <cmext/string_view>
#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
@@ -119,19 +120,6 @@ public:
FIND_PACKAGE_MODE
};
- /** \brief Define log level constants. */
- enum LogLevel
- {
- LOG_UNDEFINED,
- LOG_ERROR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_STATUS,
- LOG_VERBOSE,
- LOG_DEBUG,
- LOG_TRACE
- };
-
/** \brief Define supported trace formats **/
enum TraceFormat
{
@@ -469,9 +457,10 @@ public:
bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; }
//! Get the selected log level for `message()` commands during the cmake run.
- LogLevel GetLogLevel() const { return this->MessageLogLevel; }
- void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
- static LogLevel StringToLogLevel(const std::string& levelStr);
+ Message::LogLevel GetLogLevel() const { return this->MessageLogLevel; }
+ void SetLogLevel(Message::LogLevel level) { this->MessageLogLevel = level; }
+ static Message::LogLevel StringToLogLevel(cm::string_view levelStr);
+ static std::string LogLevelToString(Message::LogLevel level);
static TraceFormat StringToTraceFormat(const std::string& levelStr);
bool HasCheckInProgress() const
@@ -612,6 +601,20 @@ public:
//! run the --open option
bool Open(const std::string& dir, bool dryRun);
+ //! run the --workflow option
+ enum class WorkflowListPresets
+ {
+ No,
+ Yes,
+ };
+ enum class WorkflowFresh
+ {
+ No,
+ Yes,
+ };
+ int Workflow(const std::string& presetName, WorkflowListPresets listPresets,
+ WorkflowFresh fresh);
+
void UnwatchUnusedCli(const std::string& var);
void WatchUnusedCli(const std::string& var);
@@ -732,7 +735,7 @@ private:
std::set<std::string> DebugFindPkgs;
std::set<std::string> DebugFindVars;
- LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
+ Message::LogLevel MessageLogLevel = Message::LogLevel::LOG_STATUS;
bool LogLevelWasSetViaCLI = false;
bool LogContext = false;
@@ -752,6 +755,16 @@ private:
void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&);
#if !defined(CMAKE_BOOTSTRAP)
+ template <typename T>
+ const T* FindPresetForWorkflow(
+ cm::static_string_view type,
+ const std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
+ const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step);
+
+ std::function<int()> BuildWorkflowStep(const std::vector<std::string>& args);
+#endif
+
+#if !defined(CMAKE_BOOTSTRAP)
std::unique_ptr<cmMakefileProfilingData> ProfilingOutput;
#endif
};
@@ -873,6 +886,7 @@ private:
F(cxx_std_17) \
F(cxx_std_20) \
F(cxx_std_23) \
+ F(cxx_std_26) \
FOR_EACH_CXX98_FEATURE(F) \
FOR_EACH_CXX11_FEATURE(F) \
FOR_EACH_CXX14_FEATURE(F)
@@ -883,7 +897,8 @@ private:
F(cuda_std_14) \
F(cuda_std_17) \
F(cuda_std_20) \
- F(cuda_std_23)
+ F(cuda_std_23) \
+ F(cuda_std_26)
#define FOR_EACH_HIP_FEATURE(F) \
F(hip_std_98) \
@@ -891,4 +906,5 @@ private:
F(hip_std_14) \
F(hip_std_17) \
F(hip_std_20) \
- F(hip_std_23)
+ F(hip_std_23) \
+ F(hip_std_26)
diff --git a/Source/cmake.version.manifest b/Source/cmake.version.manifest
index e7010c972..79e3d19ef 100644
--- a/Source/cmake.version.manifest
+++ b/Source/cmake.version.manifest
@@ -1,6 +1,6 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0"
- xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
+ xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index f931e9dbc..723932eb9 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -71,7 +71,7 @@ const char* cmDocumentationUsageNote[][2] = {
const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
{ "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
- { "--list-presets", "List available presets." },
+ { "--list-presets[=<type>]", "List available presets." },
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
{ "--fresh",
@@ -82,9 +82,9 @@ const char* cmDocumentationOptions[][2] = {
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
{ "--find-package", "Legacy pkg-config like mode. Do not use." },
- { "--graphviz=[file]",
- "Generate graphviz of dependencies, see "
- "CMakeGraphVizOptions.cmake for more." },
+ { "--graphviz=<file>",
+ "Generate graphviz of dependencies, see CMakeGraphVizOptions.cmake for "
+ "more." },
{ "--system-information [file]", "Dump information about this system." },
{ "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>",
"Set the verbosity of messages from CMake files. "
@@ -109,8 +109,7 @@ const char* cmDocumentationOptions[][2] = {
{ "--warn-uninitialized", "Warn about uninitialized values." },
{ "--no-warn-unused-cli", "Don't warn about command line options." },
{ "--check-system-vars",
- "Find problems with variable usage in system "
- "files." },
+ "Find problems with variable usage in system files." },
{ "--compile-no-warning-as-error",
"Ignore COMPILE_WARNING_AS_ERROR property and "
"CMAKE_COMPILE_WARNING_AS_ERROR variable." },
@@ -616,7 +615,7 @@ int do_build(int ac, char const* const* av)
" <dir> = Project binary directory to be built.\n"
" --preset <preset>, --preset=<preset>\n"
" = Specify a build preset.\n"
- " --list-presets\n"
+ " --list-presets[=<type>]\n"
" = List available build presets.\n"
" --parallel [<jobs>], -j [<jobs>]\n"
" = Build in parallel using the given number of jobs. \n"
@@ -627,14 +626,14 @@ int do_build(int ac, char const* const* av)
" specifies a default parallel level when this "
"option\n"
" is not given.\n"
- " --target <tgt>..., -t <tgt>... \n"
+ " -t <tgt>..., --target <tgt>...\n"
" = Build <tgt> instead of default targets.\n"
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
" --clean-first = Build target 'clean' first, then build.\n"
" (To clean only, use --target 'clean'.)\n"
" --resolve-package-references={on|only|off}\n"
" = Restore/resolve package references during build.\n"
- " --verbose, -v = Enable verbose output - if supported - including\n"
+ " -v, --verbose = Enable verbose output - if supported - including\n"
" the build commands to be executed. \n"
" -- = Pass remaining options to the native tool.\n"
;
@@ -912,6 +911,90 @@ int do_install(int ac, char const* const* av)
#endif
}
+int do_workflow(int ac, char const* const* av)
+{
+#ifdef CMAKE_BOOTSTRAP
+ std::cerr << "This cmake does not support --workflow\n";
+ return -1;
+#else
+ using WorkflowListPresets = cmake::WorkflowListPresets;
+ using WorkflowFresh = cmake::WorkflowFresh;
+ std::string presetName;
+ auto listPresets = WorkflowListPresets::No;
+ auto fresh = WorkflowFresh::No;
+
+ using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value)>;
+
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{ "--preset", CommandArgument::Values::One,
+ CommandArgument::setToValue(presetName) },
+ CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
+ [&listPresets](const std::string&) -> bool {
+ listPresets = WorkflowListPresets::Yes;
+ return true;
+ } },
+ CommandArgument{ "--fresh", CommandArgument::Values::Zero,
+ [&fresh](const std::string&) -> bool {
+ fresh = WorkflowFresh::Yes;
+ return true;
+ } },
+ };
+
+ std::vector<std::string> inputArgs;
+
+ inputArgs.reserve(ac - 2);
+ cm::append(inputArgs, av + 2, av + ac);
+
+ decltype(inputArgs.size()) i = 0;
+ for (; i < inputArgs.size(); ++i) {
+ std::string const& arg = inputArgs[i];
+ bool matched = false;
+ bool parsed = false;
+ for (auto const& m : arguments) {
+ matched = m.matches(arg);
+ if (matched) {
+ parsed = m.parse(arg, i, inputArgs);
+ break;
+ }
+ }
+ if (!(matched && parsed)) {
+ if (!matched) {
+ presetName.clear();
+ listPresets = WorkflowListPresets::No;
+ std::cerr << "Unknown argument " << arg << std::endl;
+ }
+ break;
+ }
+ }
+
+ if (presetName.empty() && listPresets == WorkflowListPresets::No) {
+ /* clang-format off */
+ std::cerr <<
+ "Usage: cmake --workflow [options]\n"
+ "Options:\n"
+ " --preset <preset> = Workflow preset to execute.\n"
+ " --list-presets = List available workflow presets.\n"
+ " --fresh = Configure a fresh build tree, removing any "
+ "existing cache file.\n"
+ ;
+ /* clang-format on */
+ return 1;
+ }
+
+ cmake cm(cmake::RoleInternal, cmState::Project);
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const cmMessageMetadata& md) {
+ cmakemainMessageCallback(msg, md, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
+
+ return cm.Workflow(presetName, listPresets, fresh);
+#endif
+}
+
int do_open(int ac, char const* const* av)
{
#ifdef CMAKE_BOOTSTRAP
@@ -981,6 +1064,9 @@ int main(int ac, char const* const* av)
if (strcmp(av[1], "--open") == 0) {
return do_open(ac, av);
}
+ if (strcmp(av[1], "--workflow") == 0) {
+ return do_workflow(ac, av);
+ }
if (strcmp(av[1], "-E") == 0) {
return do_command(ac, av, std::move(consoleBuf));
}
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 8921aa0ca..69eb19e2f 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -273,6 +273,7 @@ int main()
std::string clrest = rest;
// rc: /fo x.dir\x.rc.res -> cl: /out:x.dir\x.rc.res.dep.obj
clrest = replace(clrest, "/fo ", "/out:");
+ clrest = replace(clrest, "-fo ", "-out:");
clrest = replace(clrest, objfile, objfile + ".dep.obj ");
cl = "\"" + cl + "\" /P /DRC_INVOKED /TC ";
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 9ab39f1eb..67394f907 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -360,17 +360,29 @@ int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */,
int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
const std::vector<std::string>& orig_cmd)
{
- // Construct the clang-tidy command line by taking what was given
- // and adding our compiler command line. The clang-tidy tool will
- // automatically skip over the compiler itself and extract the
- // options.
- int ret;
std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true);
tidy_cmd.push_back(sourceFile);
- tidy_cmd.emplace_back("--");
- cm::append(tidy_cmd, orig_cmd);
+
+ // clang-tidy supports working out the compile commands from a
+ // compile_commands.json file in a directory given by a "-p" option, or by
+ // passing the compiler command line arguments after --. When the latter
+ // strategy is used and the build is using a compiler other than the system
+ // default, clang-tidy may erroneously use the system default compiler's
+ // headers instead of those from the custom compiler. It doesn't do that if
+ // given a compile_commands.json to work with instead, so prefer to use the
+ // compile_commands.json file when "-p" is present.
+ if (!cm::contains(tidy_cmd.cbegin(), tidy_cmd.cend() - 1, "-p")) {
+ // Construct the clang-tidy command line by taking what was given
+ // and adding our compiler command line. The clang-tidy tool will
+ // automatically skip over the compiler itself and extract the
+ // options. If the compiler is a custom compiler, clang-tidy might
+ // not correctly handle that with this approach.
+ tidy_cmd.emplace_back("--");
+ cm::append(tidy_cmd, orig_cmd);
+ }
// Run the tidy command line. Capture its stdout and hide its stderr.
+ int ret;
std::string stdOut;
std::string stdErr;
if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
@@ -791,6 +803,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
if (args[1] == "env") {
+#ifndef CMAKE_BOOTSTRAP
+ cmSystemTools::EnvDiff env;
+#endif
+
auto ai = args.cbegin() + 2;
auto ae = args.cend();
for (; ai != ae; ++ai) {
@@ -803,16 +819,40 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
if (cmHasLiteralPrefix(a, "--unset=")) {
// Unset environment variable.
+#ifdef CMAKE_BOOTSTRAP
cmSystemTools::UnPutEnv(a.substr(8));
+#else
+ env.UnPutEnv(a.substr(8));
+#endif
+ } else if (a == "--modify") {
+#ifdef CMAKE_BOOTSTRAP
+ std::cerr
+ << "cmake -E env: --modify not available during bootstrapping\n";
+ return 1;
+#else
+ if (++ai == ae) {
+ std::cerr << "cmake -E env: --modify missing a parameter\n";
+ return 1;
+ }
+ std::string const& op = *ai;
+ if (!env.ParseOperation(op)) {
+ std::cerr << "cmake -E env: invalid parameter to --modify: " << op
+ << '\n';
+ return 1;
+ }
+#endif
} else if (!a.empty() && a[0] == '-') {
// Environment variable and command names cannot start in '-',
// so this must be an unknown option.
- std::cerr << "cmake -E env: unknown option '" << a << '\''
- << std::endl;
+ std::cerr << "cmake -E env: unknown option '" << a << "'\n";
return 1;
} else if (a.find('=') != std::string::npos) {
// Set environment variable.
+#ifdef CMAKE_BOOTSTRAP
cmSystemTools::PutEnv(a);
+#else
+ env.PutEnv(a);
+#endif
} else {
// This is the beginning of the command.
break;
@@ -820,10 +860,14 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
if (ai == ae) {
- std::cerr << "cmake -E env: no command given" << std::endl;
+ std::cerr << "cmake -E env: no command given\n";
return 1;
}
+#ifndef CMAKE_BOOTSTRAP
+ env.ApplyToCurrentEnv();
+#endif
+
// Execute command from remaining arguments.
std::vector<std::string> cmd(ai, ae);
int retval;
@@ -1668,16 +1712,15 @@ cmsys::Status cmcmd::SymlinkInternal(std::string const& file,
}
std::string linktext = cmSystemTools::GetFilenameName(file);
#if defined(_WIN32) && !defined(__CYGWIN__)
- std::string errorMessage;
- cmsys::Status status =
- cmSystemTools::CreateSymlink(linktext, link, &errorMessage);
+ cmsys::Status status = cmSystemTools::CreateSymlinkQuietly(linktext, link);
// Creating a symlink will fail with ERROR_PRIVILEGE_NOT_HELD if the user
// does not have SeCreateSymbolicLinkPrivilege, or if developer mode is not
// active. In that case, we try to copy the file.
if (status.GetWindows() == ERROR_PRIVILEGE_NOT_HELD) {
status = cmSystemTools::CopyFileAlways(file, link);
} else if (!status) {
- cmSystemTools::Error(errorMessage);
+ cmSystemTools::Error(cmStrCat("failed to create symbolic link '", link,
+ "': ", status.GetString()));
}
return status;
#else
@@ -2242,13 +2285,18 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
// Parse the link command to extract information we need.
for (; arg != argEnd; ++arg) {
if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:YES") == 0 ||
- cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0) {
+ cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL:YES") == 0 ||
+ cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0 ||
+ cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL") == 0) {
this->Incremental = true;
- } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0) {
+ } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0 ||
+ cmSystemTools::Strucmp(arg->c_str(), "-MANIFEST:NO") == 0) {
this->LinkGeneratesManifest = false;
- } else if (cmHasLiteralPrefix(*arg, "/Fe")) {
+ } else if (cmHasLiteralPrefix(*arg, "/Fe") ||
+ cmHasLiteralPrefix(*arg, "-Fe")) {
this->TargetFile = arg->substr(3);
- } else if (cmHasLiteralPrefix(*arg, "/out:")) {
+ } else if (cmHasLiteralPrefix(*arg, "/out:") ||
+ cmHasLiteralPrefix(*arg, "-out:")) {
this->TargetFile = arg->substr(5);
}
}
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index d520c1440..f239576ef 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -43,12 +43,12 @@ public:
{
std::string Name;
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t FindData;
+ WIN32_FIND_DATAW FindData;
#endif
FileData(std::string name
#if defined(_WIN32) && !defined(__CYGWIN__)
,
- _wfinddata_t data
+ WIN32_FIND_DATAW data
#endif
)
: Name(std::move(name))
@@ -115,8 +115,8 @@ std::string Directory::GetFilePath(std::size_t i) const
bool Directory::FileIsDirectory(std::size_t i) const
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t const& data = this->Internal->Files[i].FindData;
- return (data.attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ auto const& data = this->Internal->Files[i].FindData;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#else
std::string const& path = this->GetFilePath(i);
return kwsys::SystemTools::FileIsDirectory(path);
@@ -127,9 +127,9 @@ bool Directory::FileIsSymlink(std::size_t i) const
{
std::string const& path = this->GetFilePath(i);
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t const& data = this->Internal->Files[i].FindData;
+ auto const& data = this->Internal->Files[i].FindData;
return kwsys::SystemTools::FileIsSymlinkWithAttr(
- Encoding::ToWindowsExtendedPath(path), data.attrib);
+ Encoding::ToWindowsExtendedPath(path), data.dwFileAttributes);
#else
return kwsys::SystemTools::FileIsSymlink(path);
#endif
@@ -157,7 +157,7 @@ namespace KWSYS_NAMESPACE {
Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
- intptr_t srchHandle;
+ HANDLE srchHandle;
char* buf;
size_t bufLength;
size_t n = name.size();
@@ -176,14 +176,14 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
snprintf(buf, bufLength, "%s/*", name.c_str());
}
}
- struct _wfinddata_t data; // data of current file
+ WIN32_FIND_DATAW data; // data of current file
// Now put them into the file array
srchHandle =
- _wfindfirst((wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
+ FindFirstFileW(Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
delete[] buf;
- if (srchHandle == -1) {
+ if (srchHandle == INVALID_HANDLE_VALUE) {
Status status = Status::POSIX_errno();
if (errorMessage) {
*errorMessage = status.GetString();
@@ -193,10 +193,11 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
// Loop through names
do {
- this->Internal->Files.emplace_back(Encoding::ToNarrow(data.name), data);
- } while (_wfindnext(srchHandle, &data) != -1);
+ this->Internal->Files.emplace_back(Encoding::ToNarrow(data.cFileName),
+ data);
+ } while (FindNextFileW(srchHandle, &data));
this->Internal->Path = name;
- if (_findclose(srchHandle) == -1) {
+ if (!FindClose(srchHandle)) {
Status status = Status::POSIX_errno();
if (errorMessage) {
*errorMessage = status.GetString();
@@ -209,7 +210,7 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
std::string* errorMessage)
{
- intptr_t srchHandle;
+ HANDLE srchHandle;
char* buf;
size_t bufLength;
size_t n = name.size();
@@ -222,13 +223,13 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
buf = new char[n + 2 + 1];
snprintf(buf, bufLength, "%s/*", name.c_str());
}
- struct _wfinddata_t data; // data of current file
+ WIN32_FIND_DATAW data; // data of current file
// Now put them into the file array
- srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ srchHandle = FindFirstFileW(Encoding::ToWide(buf).c_str(), &data);
delete[] buf;
- if (srchHandle == -1) {
+ if (srchHandle == INVALID_HANDLE_VALUE) {
if (errorMessage) {
if (unsigned int errorId = GetLastError()) {
LPSTR message = nullptr;
@@ -250,8 +251,8 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
unsigned long count = 0;
do {
count++;
- } while (_wfindnext(srchHandle, &data) != -1);
- _findclose(srchHandle);
+ } while (FindNextFileW(srchHandle, &data));
+ FindClose(srchHandle);
return count;
}
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 5889a4b0b..a20901cb2 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -536,9 +536,11 @@ public:
StringMap TranslationMap;
#endif
#ifdef _WIN32
- static std::string GetCasePathName(std::string const& pathIn);
+ static std::string GetCasePathName(std::string const& pathIn,
+ bool const cache);
static std::string GetActualCaseForPathCached(std::string const& path);
static const char* GetEnvBuffered(const char* key);
+ std::map<std::string, std::string, SystemToolsPathCaseCmp> FindFileMap;
std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap;
std::map<std::string, std::string> EnvMap;
#endif
@@ -571,7 +573,8 @@ public:
static SystemToolsStatic* SystemToolsStatics;
#ifdef _WIN32
-std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn)
+std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn,
+ bool const cache)
{
std::string casePath;
@@ -623,14 +626,31 @@ std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn)
} else {
std::string test_str = casePath;
test_str += path_components[idx];
- WIN32_FIND_DATAW findData;
- HANDLE hFind =
- ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
- if (INVALID_HANDLE_VALUE != hFind) {
- path_components[idx] = Encoding::ToNarrow(findData.cFileName);
- ::FindClose(hFind);
- } else {
- converting = false;
+
+ bool found_in_cache = false;
+ if (cache) {
+ auto const it = SystemToolsStatics->FindFileMap.find(test_str);
+ if (it != SystemToolsStatics->FindFileMap.end()) {
+ path_components[idx] = it->second;
+ found_in_cache = true;
+ }
+ }
+
+ if (!found_in_cache) {
+ WIN32_FIND_DATAW findData;
+ HANDLE hFind =
+ ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
+ if (INVALID_HANDLE_VALUE != hFind) {
+ auto case_file_name = Encoding::ToNarrow(findData.cFileName);
+ if (cache) {
+ SystemToolsStatics->FindFileMap.emplace(test_str,
+ case_file_name);
+ }
+ path_components[idx] = std::move(case_file_name);
+ ::FindClose(hFind);
+ } else {
+ converting = false;
+ }
}
}
}
@@ -642,19 +662,16 @@ std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn)
std::string SystemToolsStatic::GetActualCaseForPathCached(std::string const& p)
{
- // Check to see if actual case has already been called
- // for this path, and the result is stored in the PathCaseMap
- auto& pcm = SystemToolsStatics->PathCaseMap;
- {
- auto itr = pcm.find(p);
- if (itr != pcm.end()) {
- return itr->second;
- }
- }
- std::string casePath = SystemToolsStatic::GetCasePathName(p);
- if (casePath.size() <= MAX_PATH) {
- pcm[p] = casePath;
+ std::string casePath;
+
+ auto it = SystemToolsStatics->PathCaseMap.find(p);
+ if (it != SystemToolsStatics->PathCaseMap.end()) {
+ casePath = it->second;
+ } else {
+ casePath = SystemToolsStatic::GetCasePathName(p, true);
+ SystemToolsStatics->PathCaseMap.emplace(p, casePath);
}
+
return casePath;
}
#endif
@@ -3067,17 +3084,14 @@ std::string SystemTools::GetRealPath(const std::string& path,
return ret;
}
-bool SystemTools::FileIsDirectory(const std::string& inName)
+// Remove any trailing slash from the name except in a root component.
+static const char* RemoveTrailingSlashes(
+ const std::string& inName, char (&local_buffer)[KWSYS_SYSTEMTOOLS_MAXPATH],
+ std::string& string_buffer)
{
- if (inName.empty()) {
- return false;
- }
size_t length = inName.size();
const char* name = inName.c_str();
- // Remove any trailing slash from the name except in a root component.
- char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
- std::string string_buffer;
size_t last = length - 1;
if (last > 0 && (name[last] == '/' || name[last] == '\\') &&
strcmp(name, "/") != 0 && name[last - 1] != ':') {
@@ -3091,6 +3105,19 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
}
}
+ return name;
+}
+
+bool SystemTools::FileIsDirectory(const std::string& inName)
+{
+ if (inName.empty()) {
+ return false;
+ }
+
+ char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
+ std::string string_buffer;
+ const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer);
+
// Now check the file node type.
#if defined(_WIN32)
DWORD attr =
@@ -3107,9 +3134,21 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
}
}
-bool SystemTools::FileIsExecutable(const std::string& name)
+bool SystemTools::FileIsExecutable(const std::string& inName)
{
- return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE);
+#ifdef _WIN32
+ char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
+ std::string string_buffer;
+ const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer);
+ const auto attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
+
+ // On Windows any file that exists and is not a directory is considered
+ // readable and therefore also executable:
+ return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
+#else
+ return !FileIsDirectory(inName) && TestFileAccess(inName, TEST_FILE_EXECUTE);
+#endif
}
#if defined(_WIN32)
@@ -3655,7 +3694,7 @@ std::string SystemTools::RelativePath(const std::string& local,
std::string SystemTools::GetActualCaseForPath(const std::string& p)
{
#ifdef _WIN32
- return SystemToolsStatic::GetCasePathName(p);
+ return SystemToolsStatic::GetCasePathName(p, false);
#else
return p;
#endif
diff --git a/Templates/MSBuild/FlagTables/v10_CSharp.json b/Templates/MSBuild/FlagTables/v10_CSharp.json
index 53418416c..526bcdaed 100644
--- a/Templates/MSBuild/FlagTables/v10_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v10_CSharp.json
@@ -477,21 +477,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v10_Cuda.json b/Templates/MSBuild/FlagTables/v10_Cuda.json
index b3230acab..b0765f589 100644
--- a/Templates/MSBuild/FlagTables/v10_Cuda.json
+++ b/Templates/MSBuild/FlagTables/v10_Cuda.json
@@ -70,118 +70,6 @@
]
},
{
- "name": "cmake-temp-gencode",
- "switch": "gencode=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "gencode",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "-generate-code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "-generate-code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "-gpu-code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "-gpu-code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "arch=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "arch",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "-gpu-architecture=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "-gpu-architecture",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
"name": "FastMath",
"switch": "use_fast_math",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v11_CSharp.json b/Templates/MSBuild/FlagTables/v11_CSharp.json
index 53418416c..526bcdaed 100644
--- a/Templates/MSBuild/FlagTables/v11_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v11_CSharp.json
@@ -477,21 +477,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v12_CSharp.json b/Templates/MSBuild/FlagTables/v12_CSharp.json
index 53418416c..526bcdaed 100644
--- a/Templates/MSBuild/FlagTables/v12_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v12_CSharp.json
@@ -477,21 +477,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v140_CSharp.json b/Templates/MSBuild/FlagTables/v140_CSharp.json
index 53418416c..526bcdaed 100644
--- a/Templates/MSBuild/FlagTables/v140_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v140_CSharp.json
@@ -477,21 +477,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v141_CSharp.json b/Templates/MSBuild/FlagTables/v141_CSharp.json
index 53418416c..526bcdaed 100644
--- a/Templates/MSBuild/FlagTables/v141_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v141_CSharp.json
@@ -477,21 +477,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json
index 9ea8f4baa..d57a97e1f 100644
--- a/Templates/MSBuild/FlagTables/v142_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v142_CSharp.json
@@ -495,21 +495,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Templates/MSBuild/FlagTables/v143_CSharp.json b/Templates/MSBuild/FlagTables/v143_CSharp.json
index 9ea8f4baa..d57a97e1f 100644
--- a/Templates/MSBuild/FlagTables/v143_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v143_CSharp.json
@@ -495,21 +495,21 @@
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib",
"comment": "",
"value": "true",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib-",
"comment": "",
"value": "false",
"flags": []
},
{
- "name": "NoStandardLib",
+ "name": "NoStdLib",
"switch": "nostdlib+",
"comment": "",
"value": "true",
diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt
index 1b7e57d28..8f6b35568 100644
--- a/Tests/Assembler/CMakeLists.txt
+++ b/Tests/Assembler/CMakeLists.txt
@@ -24,6 +24,12 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND
elseif("${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
list(APPEND C_FLAGS -arch arm64)
endif()
+ if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ # Just in case the user is passing -flto, we need to pass -fno-lto to
+ # clang when generating the assembly file, or else clang will generate
+ # LLVM IR instead of assembly.
+ list(APPEND C_FLAGS -fno-lto)
+ endif()
# Clang on OS X, and perhaps other compilers, do not support -g
# for both generating and assembling, so drop it from generating.
list(REMOVE_ITEM C_FLAGS -g)
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index 1d45162d0..612d4b4d8 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -47,12 +47,10 @@ if(WIN32)
list(APPEND CMakeLib_TESTS
testVisualStudioSlnParser.cxx
)
- configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testVisualStudioSlnParser.h.in
- ${CMAKE_CURRENT_BINARY_DIR}/testVisualStudioSlnParser.h @ONLY)
+ configure_file(testVisualStudioSlnParser.h.in testVisualStudioSlnParser.h @ONLY)
endif()
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testXMLParser.h.in
- ${CMAKE_CURRENT_BINARY_DIR}/testXMLParser.h @ONLY)
+configure_file(testXMLParser.h.in testXMLParser.h @ONLY)
create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS})
add_executable(CMakeLibTests ${CMakeLib_TEST_SRCS})
diff --git a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
index 4bef6c5e0..b4bc92179 100644
--- a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
+++ b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
@@ -1,6 +1,6 @@
-foreach (_retval 0 1)
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/memtester.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/ret${_retval}.cxx" @ONLY)
-endforeach ()
+foreach(_retval IN ITEMS 0 1)
+ configure_file(memtester.cxx.in ret${_retval}.cxx @ONLY)
+endforeach()
include_directories(${CMake_SOURCE_DIR}/Source ${CMake_BINARY_DIR}/Source)
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 965690c37..e044794ba 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -1,57 +1,182 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include <functional>
#include <initializer_list>
#include <iostream>
+#include <map>
#include <string>
+#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
namespace {
-struct Result
+struct Result : public ArgumentParser::ParseResult
{
bool Option1 = false;
bool Option2 = false;
std::string String1;
- std::string String2;
+ cm::optional<std::string> String2;
+ cm::optional<std::string> String3;
+ ArgumentParser::Maybe<std::string> String4;
+ ArgumentParser::NonEmpty<std::string> String5;
+ ArgumentParser::NonEmpty<std::string> String6;
- std::vector<std::string> List1;
- std::vector<std::string> List2;
- std::vector<std::string> List3;
+ ArgumentParser::NonEmpty<std::vector<std::string>> List1;
+ ArgumentParser::NonEmpty<std::vector<std::string>> List2;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List3;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List4;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List5;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> List6;
std::vector<std::vector<std::string>> Multi1;
std::vector<std::vector<std::string>> Multi2;
- std::vector<std::vector<std::string>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi4;
+
+ cm::optional<std::string> Pos0;
+ cm::optional<std::string> Pos1;
+ cm::optional<std::string> Pos2;
+
+ bool Func0_ = false;
+ ArgumentParser::Continue Func0(cm::string_view)
+ {
+ Func0_ = true;
+ return ArgumentParser::Continue::No;
+ }
+
+ std::string Func1_;
+ ArgumentParser::Continue Func1(cm::string_view arg)
+ {
+ Func1_ = std::string(arg);
+ return ArgumentParser::Continue::No;
+ }
+
+ std::map<std::string, std::vector<std::string>> Func2_;
+ ArgumentParser::Continue Func2(cm::string_view key, cm::string_view arg)
+ {
+ Func2_[std::string(key)].emplace_back(arg);
+ return key == "FUNC_2b" ? ArgumentParser::Continue::Yes
+ : ArgumentParser::Continue::No;
+ }
+
+ std::vector<std::string> Func3_;
+ ArgumentParser::Continue Func3(cm::string_view arg)
+ {
+ Func3_.emplace_back(arg);
+ return ArgumentParser::Continue::Yes;
+ }
+
+ std::map<std::string, std::vector<std::string>> Func4_;
+ ArgumentParser::Continue Func4(cm::string_view key, cm::string_view arg)
+ {
+ Func4_[std::string(key)].emplace_back(arg);
+ return key == "FUNC_4b" ? ArgumentParser::Continue::Yes
+ : ArgumentParser::Continue::No;
+ }
+
+ ArgumentParser::Maybe<std::string> UnboundMaybe{ 'u', 'n', 'b', 'o',
+ 'u', 'n', 'd' };
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> UnboundMaybeEmpty{
+ 1, "unbound"
+ };
+ ArgumentParser::NonEmpty<std::vector<std::string>> UnboundNonEmpty{
+ 1, "unbound"
+ };
+ ArgumentParser::NonEmpty<std::string> UnboundNonEmptyStr{ 'u', 'n', 'b', 'o',
+ 'u', 'n', 'd' };
+
+ std::vector<cm::string_view> ParsedKeywords;
};
std::initializer_list<cm::string_view> const args = {
/* clang-format off */
+ "pos0", // position index 0
"OPTION_1", // option
+ "pos2", // position index 2, ignored because after keyword
+ // "OPTION_2", // option that is not present
"STRING_1", // string arg missing value
- "STRING_2", "foo", "bar", // string arg + unparsed value
+ "STRING_2", "foo", "bar", // string arg + unparsed value, presence captured
+ // "STRING_3", // string arg that is not present
+ "STRING_4", // string arg allowed to be missing value
+ "STRING_5", "foo", // string arg that is not empty
+ "STRING_6", "", // string arg that is empty
"LIST_1", // list arg missing values
"LIST_2", "foo", "bar", // list arg with 2 elems
"LIST_3", "bar", // list arg ...
"LIST_3", "foo", // ... with continuation
+ "LIST_4", // list arg missing values, presence captured
+ // "LIST_5", // list arg that is not present
+ "LIST_6", // list arg allowed to be empty
"MULTI_2", // multi list with 0 lists
"MULTI_3", "foo", "bar", // multi list with first list with two elems
"MULTI_3", "bar", "foo", // multi list with second list with two elems
+ // "MULTI_4", // multi list arg that is not present
+ "FUNC_0", // callback arg missing value
+ "FUNC_1", "foo", "ign1", // callback with one arg + unparsed value
+ "FUNC_2a", "foo", "ign2", // callback with keyword-dependent arg count
+ "FUNC_2b", "bar", "zot", // callback with keyword-dependent arg count
+ "FUNC_3", "foo", "bar", // callback with list arg ...
+ "FUNC_4a", "foo", "ign4", // callback with keyword-dependent arg count
+ "FUNC_4b", "bar", "zot", // callback with keyword-dependent arg count
/* clang-format on */
};
bool verifyResult(Result const& result,
- std::vector<std::string> const& unparsedArguments,
- std::vector<std::string> const& keywordsMissingValue)
+ std::vector<std::string> const& unparsedArguments)
{
static std::vector<std::string> const foobar = { "foo", "bar" };
static std::vector<std::string> const barfoo = { "bar", "foo" };
- static std::vector<std::string> const missing = { "STRING_1", "LIST_1" };
+ static std::vector<std::string> const unbound = { "unbound" };
+ static std::vector<cm::string_view> const parsedKeywords = {
+ /* clang-format off */
+ "OPTION_1",
+ "STRING_1",
+ "STRING_2",
+ "STRING_4",
+ "STRING_5",
+ "STRING_6",
+ "LIST_1",
+ "LIST_2",
+ "LIST_3",
+ "LIST_3",
+ "LIST_4",
+ "LIST_6",
+ "MULTI_2",
+ "MULTI_3",
+ "MULTI_3",
+ "FUNC_0",
+ "FUNC_1",
+ "FUNC_2a",
+ "FUNC_2b",
+ "FUNC_3",
+ "FUNC_4a",
+ "FUNC_4b",
+ /* clang-format on */
+ };
+ static std::map<std::string, std::vector<std::string>> const func2map = {
+ { "FUNC_2a", { "foo" } }, { "FUNC_2b", { "bar", "zot" } }
+ };
+ static std::map<std::string, std::vector<std::string>> const func4map = {
+ { "FUNC_4a", { "foo" } }, { "FUNC_4b", { "bar", "zot" } }
+ };
+ static std::map<cm::string_view, std::string> const keywordErrors = {
+ { "STRING_1"_s, " missing required value\n" },
+ { "STRING_6"_s, " empty string not allowed\n" },
+ { "LIST_1"_s, " missing required value\n" },
+ { "LIST_4"_s, " missing required value\n" },
+ { "FUNC_0"_s, " missing required value\n" }
+ };
+ static std::vector<std::string> const unparsed = { "pos2", "bar", "ign1",
+ "ign2", "ign4" };
#define ASSERT_TRUE(x) \
do { \
@@ -61,26 +186,63 @@ bool verifyResult(Result const& result,
} \
} while (false)
+ ASSERT_TRUE(!result);
+
ASSERT_TRUE(result.Option1);
ASSERT_TRUE(!result.Option2);
ASSERT_TRUE(result.String1.empty());
- ASSERT_TRUE(result.String2 == "foo");
+ ASSERT_TRUE(result.String2);
+ ASSERT_TRUE(*result.String2 == "foo");
+ ASSERT_TRUE(!result.String3);
+ ASSERT_TRUE(result.String4.empty());
+ ASSERT_TRUE(result.String5 == "foo");
+ ASSERT_TRUE(result.String6.empty());
ASSERT_TRUE(result.List1.empty());
ASSERT_TRUE(result.List2 == foobar);
- ASSERT_TRUE(result.List3 == barfoo);
+ ASSERT_TRUE(result.List3);
+ ASSERT_TRUE(*result.List3 == barfoo);
+ ASSERT_TRUE(result.List4);
+ ASSERT_TRUE(result.List4->empty());
+ ASSERT_TRUE(!result.List5);
+ ASSERT_TRUE(result.List6);
+ ASSERT_TRUE(result.List6->empty());
ASSERT_TRUE(result.Multi1.empty());
ASSERT_TRUE(result.Multi2.size() == 1);
ASSERT_TRUE(result.Multi2[0].empty());
- ASSERT_TRUE(result.Multi3.size() == 2);
- ASSERT_TRUE(result.Multi3[0] == foobar);
- ASSERT_TRUE(result.Multi3[1] == barfoo);
+ ASSERT_TRUE(result.Multi3);
+ ASSERT_TRUE((*result.Multi3).size() == 2);
+ ASSERT_TRUE((*result.Multi3)[0] == foobar);
+ ASSERT_TRUE((*result.Multi3)[1] == barfoo);
+ ASSERT_TRUE(!result.Multi4);
+
+ ASSERT_TRUE(result.Pos0 == "pos0");
+ ASSERT_TRUE(!result.Pos1);
+ ASSERT_TRUE(!result.Pos2);
+
+ ASSERT_TRUE(result.Func0_ == false);
+ ASSERT_TRUE(result.Func1_ == "foo");
+ ASSERT_TRUE(result.Func2_ == func2map);
+ ASSERT_TRUE(result.Func3_ == foobar);
+ ASSERT_TRUE(result.Func4_ == func4map);
+
+ ASSERT_TRUE(unparsedArguments == unparsed);
- ASSERT_TRUE(unparsedArguments.size() == 1);
- ASSERT_TRUE(unparsedArguments[0] == "bar");
- ASSERT_TRUE(keywordsMissingValue == missing);
+ ASSERT_TRUE(result.UnboundMaybe == "unbound");
+ ASSERT_TRUE(result.UnboundMaybeEmpty == unbound);
+ ASSERT_TRUE(result.UnboundNonEmpty == unbound);
+ ASSERT_TRUE(result.UnboundNonEmptyStr == "unbound");
+
+ ASSERT_TRUE(result.ParsedKeywords == parsedKeywords);
+
+ ASSERT_TRUE(result.GetKeywordErrors().size() == keywordErrors.size());
+ for (auto const& ke : result.GetKeywordErrors()) {
+ auto const ki = keywordErrors.find(ke.first);
+ ASSERT_TRUE(ki != keywordErrors.end());
+ ASSERT_TRUE(ke.second == ki->second);
+ }
return true;
}
@@ -89,45 +251,116 @@ bool testArgumentParserDynamic()
{
Result result;
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
-
- cmArgumentParser<void>{}
- .Bind("OPTION_1"_s, result.Option1)
- .Bind("OPTION_2"_s, result.Option2)
- .Bind("STRING_1"_s, result.String1)
- .Bind("STRING_2"_s, result.String2)
- .Bind("LIST_1"_s, result.List1)
- .Bind("LIST_2"_s, result.List2)
- .Bind("LIST_3"_s, result.List3)
- .Bind("MULTI_1"_s, result.Multi1)
- .Bind("MULTI_2"_s, result.Multi2)
- .Bind("MULTI_3"_s, result.Multi3)
- .Parse(args, &unparsedArguments, &keywordsMissingValue);
-
- return verifyResult(result, unparsedArguments, keywordsMissingValue);
+
+ std::function<ArgumentParser::Continue(cm::string_view, cm::string_view)>
+ func4 = [&result](cm::string_view key,
+ cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func4(key, arg);
+ };
+
+ static_cast<ArgumentParser::ParseResult&>(result) =
+ cmArgumentParser<void>{}
+ .Bind(0, result.Pos0)
+ .Bind(1, result.Pos1)
+ .Bind(2, result.Pos2)
+ .Bind("OPTION_1"_s, result.Option1)
+ .Bind("OPTION_2"_s, result.Option2)
+ .Bind("STRING_1"_s, result.String1)
+ .Bind("STRING_2"_s, result.String2)
+ .Bind("STRING_3"_s, result.String3)
+ .Bind("STRING_4"_s, result.String4)
+ .Bind("STRING_5"_s, result.String5)
+ .Bind("STRING_6"_s, result.String6)
+ .Bind("LIST_1"_s, result.List1)
+ .Bind("LIST_2"_s, result.List2)
+ .Bind("LIST_3"_s, result.List3)
+ .Bind("LIST_4"_s, result.List4)
+ .Bind("LIST_5"_s, result.List5)
+ .Bind("LIST_6"_s, result.List6)
+ .Bind("MULTI_1"_s, result.Multi1)
+ .Bind("MULTI_2"_s, result.Multi2)
+ .Bind("MULTI_3"_s, result.Multi3)
+ .Bind("MULTI_4"_s, result.Multi4)
+ .Bind("FUNC_0"_s,
+ [&result](cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func0(arg);
+ })
+ .Bind("FUNC_1"_s,
+ [&result](cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func1(arg);
+ })
+ .Bind("FUNC_2a"_s,
+ [&result](cm::string_view key, cm::string_view arg)
+ -> ArgumentParser::Continue { return result.Func2(key, arg); })
+ .Bind("FUNC_2b"_s,
+ [&result](cm::string_view key, cm::string_view arg)
+ -> ArgumentParser::Continue { return result.Func2(key, arg); })
+ .Bind("FUNC_3"_s,
+ [&result](cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func3(arg);
+ })
+ .Bind("FUNC_4a"_s, func4)
+ .Bind("FUNC_4b"_s, func4)
+ .BindParsedKeywords(result.ParsedKeywords)
+ .Parse(args, &unparsedArguments);
+
+ return verifyResult(result, unparsedArguments);
}
+static auto const parserStaticFunc4 =
+ [](Result& result, cm::string_view key,
+ cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func4(key, arg);
+};
+static auto const parserStatic = //
+ cmArgumentParser<Result>{}
+ .Bind(0, &Result::Pos0)
+ .Bind(1, &Result::Pos1)
+ .Bind(2, &Result::Pos2)
+ .Bind("OPTION_1"_s, &Result::Option1)
+ .Bind("OPTION_2"_s, &Result::Option2)
+ .Bind("STRING_1"_s, &Result::String1)
+ .Bind("STRING_2"_s, &Result::String2)
+ .Bind("STRING_3"_s, &Result::String3)
+ .Bind("STRING_4"_s, &Result::String4)
+ .Bind("STRING_5"_s, &Result::String5)
+ .Bind("STRING_6"_s, &Result::String6)
+ .Bind("LIST_1"_s, &Result::List1)
+ .Bind("LIST_2"_s, &Result::List2)
+ .Bind("LIST_3"_s, &Result::List3)
+ .Bind("LIST_4"_s, &Result::List4)
+ .Bind("LIST_5"_s, &Result::List5)
+ .Bind("LIST_6"_s, &Result::List6)
+ .Bind("MULTI_1"_s, &Result::Multi1)
+ .Bind("MULTI_2"_s, &Result::Multi2)
+ .Bind("MULTI_3"_s, &Result::Multi3)
+ .Bind("MULTI_4"_s, &Result::Multi4)
+ .Bind("FUNC_0"_s, &Result::Func0)
+ .Bind("FUNC_1"_s, &Result::Func1)
+ .Bind("FUNC_2a"_s, &Result::Func2)
+ .Bind("FUNC_2b"_s, &Result::Func2)
+ .Bind("FUNC_3"_s,
+ [](Result& result, cm::string_view arg) -> ArgumentParser::Continue {
+ return result.Func3(arg);
+ })
+ .Bind("FUNC_4a"_s, parserStaticFunc4)
+ .Bind("FUNC_4b"_s, parserStaticFunc4)
+ .BindParsedKeywords(&Result::ParsedKeywords)
+ /* keep semicolon on own line */;
+
bool testArgumentParserStatic()
{
- static auto const parser = //
- cmArgumentParser<Result>{}
- .Bind("OPTION_1"_s, &Result::Option1)
- .Bind("OPTION_2"_s, &Result::Option2)
- .Bind("STRING_1"_s, &Result::String1)
- .Bind("STRING_2"_s, &Result::String2)
- .Bind("LIST_1"_s, &Result::List1)
- .Bind("LIST_2"_s, &Result::List2)
- .Bind("LIST_3"_s, &Result::List3)
- .Bind("MULTI_1"_s, &Result::Multi1)
- .Bind("MULTI_2"_s, &Result::Multi2)
- .Bind("MULTI_3"_s, &Result::Multi3);
-
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- Result const result =
- parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+ Result const result = parserStatic.Parse(args, &unparsedArguments);
+ return verifyResult(result, unparsedArguments);
+}
- return verifyResult(result, unparsedArguments, keywordsMissingValue);
+bool testArgumentParserStaticBool()
+{
+ std::vector<std::string> unparsedArguments;
+ Result result;
+ ASSERT_TRUE(parserStatic.Parse(result, args, &unparsedArguments) == false);
+ return verifyResult(result, unparsedArguments);
}
} // namespace
@@ -144,5 +377,10 @@ int testArgumentParser(int /*unused*/, char* /*unused*/ [])
return -1;
}
+ if (!testArgumentParserStaticBool()) {
+ std::cout << "While executing testArgumentParserStaticBool().\n";
+ return -1;
+ }
+
return 0;
}
diff --git a/Tests/CMakeLib/testCMExtEnumSet.cxx b/Tests/CMakeLib/testCMExtEnumSet.cxx
index 64c437b29..dbb0a542e 100644
--- a/Tests/CMakeLib/testCMExtEnumSet.cxx
+++ b/Tests/CMakeLib/testCMExtEnumSet.cxx
@@ -191,6 +191,15 @@ void testEdition()
++failed;
}
}
+ {
+ cm::enum_set<Test> testSet1;
+ cm::enum_set<Test> testSet2{ Test::A, Test::C, Test::B };
+
+ testSet1 = { Test::A, Test::C, Test::B };
+ if (testSet1.size() != 3 || testSet1 != testSet2) {
+ ++failed;
+ }
+ }
}
}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 3e400c2f3..6e35df90d 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -40,10 +40,10 @@ set(ENV{HOME} \"${TEST_HOME}\")
endif()
# Suppress generator deprecation warnings in test suite.
-if(CMAKE_GENERATOR MATCHES "^Visual Studio 10 2010")
- set(TEST_WARN_VS10_CODE "set(ENV{CMAKE_WARN_VS10} OFF)")
+if(CMAKE_GENERATOR MATCHES "^Visual Studio 11 2012")
+ set(TEST_WARN_VS11_CODE "set(ENV{CMAKE_WARN_VS11} OFF)")
else()
- set(TEST_WARN_VS10_CODE "")
+ set(TEST_WARN_VS11_CODE "")
endif()
# 3.9 or later provides a definitive answer to whether we are multi-config
@@ -89,7 +89,7 @@ if(BUILD_TESTING)
endif()
endif()
- set(MAKE_IS_GNU )
+ set(MAKE_IS_GNU)
if(CMAKE_MAKE_PROGRAM MATCHES make)
execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} no_such_target --version
RESULT_VARIABLE res OUTPUT_VARIABLE out ERROR_VARIABLE out)
@@ -101,7 +101,7 @@ if(BUILD_TESTING)
endif()
# some old versions of make simply cannot handle spaces in paths
- if (MAKE_IS_GNU OR
+ if(MAKE_IS_GNU OR
CMAKE_MAKE_PROGRAM MATCHES "nmake|gmake|wmake" OR
CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland|Ninja")
set(MAKE_SUPPORTS_SPACES 1)
@@ -181,7 +181,7 @@ if(BUILD_TESTING)
ERROR_VARIABLE my_err)
string(REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Wow6432Node\\\\Microsoft\\\\Windows CE Tools\\\\SDKs\\\\" ";" sdk_list "${sdk_reg}")
list(LENGTH sdk_list sdk_list_len)
- if (${sdk_list_len} GREATER 1)
+ if(${sdk_list_len} GREATER 1)
list(GET sdk_list 1 _sdk) # The first entry is always empty due to the regex replace above
string(STRIP ${_sdk} _sdk) # Make sure there is no newline in the SDK name
endif()
@@ -205,7 +205,7 @@ if(BUILD_TESTING)
select_wince_sdk(reg_wince wince_sdk)
set(reg_tegra "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;sdkRoot]")
set(reg_nasm "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]")
- foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm)
+ foreach(reg IN ITEMS vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm)
get_filename_component(r "${reg_${reg}}" ABSOLUTE)
if(IS_DIRECTORY "${r}" AND NOT "${r}" STREQUAL "/registry")
set(${reg} 1)
@@ -227,7 +227,7 @@ if(BUILD_TESTING)
set(vs_versions vs15)
endif()
endif()
- foreach(info ${vs_versions})
+ foreach(info IN LISTS vs_versions)
cmake_host_system_information(RESULT found QUERY "${info_${info}}")
if(found)
set(${info} 1)
@@ -287,12 +287,12 @@ if(BUILD_TESTING)
"Should the long tests be run (such as Bootstrap)." ON)
mark_as_advanced(CMAKE_RUN_LONG_TESTS)
- if (CMAKE_RUN_LONG_TESTS)
+ if(CMAKE_RUN_LONG_TESTS)
option(CTEST_TEST_CTEST
"Should the tests that run a full sub ctest process be run?"
OFF)
mark_as_advanced(CTEST_TEST_CTEST)
- endif ()
+ endif()
option(CTEST_TEST_CPACK
"Should the tests that use '--build-target package' be run?"
@@ -367,9 +367,9 @@ if(BUILD_TESTING)
if(CMake_TEST_RESOURCES)
ADD_TEST_MACRO(VSResource VSResource)
- if (CMAKE_GENERATOR MATCHES "Ninja")
+ if(CMAKE_GENERATOR MATCHES "Ninja")
add_test_macro(VSResourceNinjaForceRSP VSResourceNinjaForceRSP)
- endif ()
+ endif()
endif()
if(_isMultiConfig)
set(MSManifest_CTEST_OPTIONS -C $<CONFIGURATION>)
@@ -394,6 +394,9 @@ if(BUILD_TESTING)
if(CMake_TEST_XCODE_SWIFT)
ADD_TEST_MACRO(SwiftMix SwiftMix)
endif()
+ if(CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 5.1)
+ ADD_TEST_MACRO(SwiftMixLib Swifty)
+ endif()
endif()
if(CMAKE_Fortran_COMPILER)
ADD_TEST_MACRO(FortranOnly FortranOnly)
@@ -431,7 +434,7 @@ if(BUILD_TESTING)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
- if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
endif()
@@ -499,7 +502,7 @@ if(BUILD_TESTING)
endif()
ADD_TEST_MACRO(SourcesProperty SourcesProperty)
ADD_TEST_MACRO(SourceFileProperty SourceFileProperty)
- if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+ if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
ADD_TEST_MACRO(SourceFileIncludeDirProperty SourceFileIncludeDirProperty)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "LCC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
@@ -618,6 +621,11 @@ if(BUILD_TESTING)
set(Module.CheckIPOSupported-CXX_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_CXX=${CMake_TEST_IPO_WORKS_CXX})
ADD_TEST_MACRO(Module.CheckIPOSupported-CXX CheckIPOSupported-CXX)
+ if(CMake_TEST_CUDA)
+ ADD_TEST_MACRO(Module.CheckIPOSupported-CUDA CheckIPOSupported-CUDA)
+ set_property(TEST Module.CheckIPOSupported-CUDA APPEND PROPERTY LABELS "CUDA")
+ endif()
+
if(CMAKE_Fortran_COMPILER)
set(Module.CheckIPOSupported-Fortran_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_Fortran=${CMake_TEST_IPO_WORKS_Fortran})
ADD_TEST_MACRO(Module.CheckIPOSupported-Fortran CheckIPOSupported-Fortran)
@@ -641,11 +649,11 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(Module.WriteCompilerDetectionHeader WriteCompilerDetectionHeader)
- if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC")
+ if(APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fPIE run_pic_test)
else()
- if (CMAKE_CXX_COMPILER_ID MATCHES "PGI"
+ if(CMAKE_CXX_COMPILER_ID MATCHES "PGI"
OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale"
OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(run_pic_test 0)
@@ -654,7 +662,7 @@ if(BUILD_TESTING)
endif()
endif()
- if (run_pic_test)
+ if(run_pic_test)
ADD_TEST_MACRO(PositionIndependentTargets PositionIndependentTargets)
endif()
@@ -725,13 +733,15 @@ if(BUILD_TESTING)
# mainly it tests that cmake doesn't crash when generating these project files.
if(CMAKE_GENERATOR MATCHES "^(Unix Makefiles|Ninja)$"
AND NOT "${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
- foreach(extraGenerator
+ foreach(
+ extraGenerator
+ IN ITEMS
"CodeBlocks"
"CodeLite"
"Eclipse CDT4"
"Kate"
"Sublime Text 2"
- )
+ )
string(REPLACE " " "" extraGeneratorTestName "Simple_${extraGenerator}Generator")
add_test(${extraGeneratorTestName} ${CMAKE_CTEST_COMMAND}
--build-and-test
@@ -786,7 +796,7 @@ if(BUILD_TESTING)
--build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo"
--test-command foo
)
- set_tests_properties ( SubProject-Stage2 PROPERTIES DEPENDS SubProject)
+ set_tests_properties(SubProject-Stage2 PROPERTIES DEPENDS SubProject)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubProject")
endif()
@@ -1056,8 +1066,11 @@ if(BUILD_TESTING)
endif()
endif()
if(NSIS_MAKENSIS_EXECUTABLE)
- set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
- -DCPACK_BINARY_NSIS:BOOL=ON)
+ execute_process(COMMAND ${NSIS_MAKENSIS_EXECUTABLE} "-VERSION" ERROR_QUIET OUTPUT_QUIET RESULT_VARIABLE NSIS_OK)
+ if("${NSIS_OK}" STREQUAL "0")
+ set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
+ -DCPACK_BINARY_NSIS:BOOL=ON)
+ endif()
endif()
add_test(CPackComponents ${CMAKE_CTEST_COMMAND}
@@ -1119,7 +1132,7 @@ if(BUILD_TESTING)
set(CPACK_GENERATOR_STRING_${CPackGen} ${CPackGen})
endif()
set(CPackRun_CPackGen "-DCPackGen=${CPACK_GENERATOR_STRING_${CPackGen}}")
- foreach(CPackComponentWay ${CWAYLST})
+ foreach(CPackComponentWay IN LISTS CWAYLST)
set(CPackRun_CPackComponentWay "-DCPackComponentWay=${CPackComponentWay}")
add_test(CPackComponentsForAll-${CPackGen}-${CPackComponentWay}
${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE}
@@ -1153,7 +1166,6 @@ if(BUILD_TESTING)
"components-source"
"components-shlibdeps1"
"components-depend1"
- "components-depend2"
"compression")
# Run additional tests if dpkg-shlibdeps is available (and is new enough version)
find_program(SHLIBDEPS_EXECUTABLE NAMES dpkg-shlibdeps)
@@ -1173,6 +1185,11 @@ if(BUILD_TESTING)
list(APPEND DEB_CONFIGURATIONS_TO_TEST "shlibdeps-with-private-lib-failure"
"shlibdeps-with-private-lib-success")
endif()
+ # Check if distro has symbols or shlibs data
+ file(GLOB SHLIBS_FILES_EXIST "/var/lib/dpkg/info/*.shlibs" "/var/lib/dpkg/info/*.symbols")
+ if(SHLIBS_FILES_EXIST)
+ list(APPEND DEB_CONFIGURATIONS_TO_TEST "components-depend2")
+ endif()
endif()
set(CPackGen "DEB")
@@ -1338,7 +1355,7 @@ if(BUILD_TESTING)
--test-command complex)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ComplexOneConfig")
# because of the registry write these tests depend on each other
- set_tests_properties ( complex PROPERTIES DEPENDS complexOneConfig)
+ set_tests_properties(complex PROPERTIES DEPENDS complexOneConfig)
add_test(Environment ${CMAKE_CTEST_COMMAND}
--build-and-test
@@ -1421,62 +1438,66 @@ if(BUILD_TESTING)
endif()
# test for Find modules, simple cases
- foreach(_mod IN ITEMS
- ALSA
- Boost
- BLAS
- BZip2
- CURL
- Cups
- Doxygen
- DevIL
- EnvModules
- EXPAT
- Fontconfig
- Freetype
- GDAL
- GIF
- Git
- GLEW
- GLUT
- GnuTLS
- GSL
- GTK2
- Iconv
- ICU
- Intl
- Jasper
- JNI
- JPEG
- JsonCpp
- LAPACK
- LibArchive
- LibLZMA
- LibRHash
- Libinput
- LibUV
- LibXml2
- LibXslt
- LTTngUST
- ODBC
- OpenACC
- OpenCL
- OpenGL
- OpenMP
- OpenSSL
- MPI
- PNG
- Patch
- PostgreSQL
- Protobuf
- SDL
- SQLite3
- TIFF
- Vulkan
- X11
- XalanC
- XercesC
- )
+ foreach(
+ _mod
+ IN ITEMS
+ ALSA
+ BLAS
+ Boost
+ BZip2
+ Cups
+ CURL
+ DevIL
+ Doxygen
+ EnvModules
+ EXPAT
+ Fontconfig
+ Freetype
+ GDAL
+ GIF
+ Git
+ GLEW
+ GLUT
+ GnuTLS
+ GSL
+ GTK2
+ Iconv
+ ICU
+ Intl
+ Jasper
+ JNI
+ JPEG
+ JsonCpp
+ LAPACK
+ LibArchive
+ Libinput
+ LibLZMA
+ LibRHash
+ LibUV
+ LibXml2
+ LibXslt
+ LTTngUST
+ MPI
+ ODBC
+ OpenACC
+ OpenAL
+ OpenCL
+ OpenGL
+ OpenMP
+ OpenSP
+ OpenSSL
+ Patch
+ PNG
+ PostgreSQL
+ Protobuf
+ SDL
+ SQLite3
+ TIFF
+ Vulkan
+ X11
+ XalanC
+ XercesC
+ )
if(CMake_TEST_Find${_mod})
add_subdirectory(Find${_mod})
endif()
@@ -1522,7 +1543,7 @@ if(BUILD_TESTING)
# CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux
if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_ROOT_DIR OR
CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR)
- set(FindMatlab_additional_test_options )
+ set(FindMatlab_additional_test_options)
if(CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR)
set(FindMatlab_additional_test_options -DIS_MCR=TRUE)
endif()
@@ -1556,7 +1577,7 @@ if(BUILD_TESTING)
endif()
set(ExternalProject_BUILD_OPTIONS "")
- foreach(vcs CVS SVN GIT HG)
+ foreach(vcs IN ITEMS CVS SVN GIT HG)
if(DEFINED CMake_TEST_ExternalProject_${vcs})
list(APPEND ExternalProject_BUILD_OPTIONS -DEP_TEST_${vcs}=${CMake_TEST_ExternalProject_${vcs}})
endif()
@@ -1656,7 +1677,8 @@ if(BUILD_TESTING)
RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}
WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
- DEPENDS ExternalProjectUpdateSetup )
+ DEPENDS ExternalProjectUpdateSetup
+ )
execute_process(
COMMAND ${CMAKE_COMMAND}
@@ -1711,7 +1733,7 @@ if(BUILD_TESTING)
function(add_tutorial_test step_name use_mymath tutorial_arg pass_regex)
set(tutorial_test_name Tutorial${step_name})
set(tutorial_build_dir "${CMake_BINARY_DIR}/Tests/Tutorial/${step_name}")
- if (use_mymath)
+ if(use_mymath)
set(tutorial_build_options "")
else()
set(tutorial_test_name ${tutorial_test_name}_MYMATH)
@@ -1735,7 +1757,7 @@ if(BUILD_TESTING)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
foreach(STP RANGE 2 12)
- if (STP EQUAL 6)
+ if(STP EQUAL 8)
set(pass_regex ".*using log and exp")
else()
set(pass_regex "The square root of 25 is 5")
@@ -1994,11 +2016,11 @@ if(BUILD_TESTING)
--test-command Exec2
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkLineOrder")
- set_tests_properties ( qtwrapping PROPERTIES DEPENDS wrapping)
- set_tests_properties ( testdriver1 PROPERTIES DEPENDS qtwrapping)
- set_tests_properties ( testdriver2 PROPERTIES DEPENDS testdriver1)
- set_tests_properties ( testdriver3 PROPERTIES DEPENDS testdriver2)
- set_tests_properties ( linkorder2 PROPERTIES DEPENDS linkorder1)
+ set_tests_properties(qtwrapping PROPERTIES DEPENDS wrapping)
+ set_tests_properties(testdriver1 PROPERTIES DEPENDS qtwrapping)
+ set_tests_properties(testdriver2 PROPERTIES DEPENDS testdriver1)
+ set_tests_properties(testdriver3 PROPERTIES DEPENDS testdriver2)
+ set_tests_properties(linkorder2 PROPERTIES DEPENDS linkorder1)
# Test static linking on toolchains known to support it.
if((CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC")
@@ -2030,9 +2052,9 @@ if(BUILD_TESTING)
"${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj"
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDirSpaces")
- endif ()
+ endif()
- if (WIN32)
+ if(WIN32)
add_test(SubDir ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/SubDir"
@@ -2044,7 +2066,7 @@ if(BUILD_TESTING)
"${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere"
"${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.obj"
)
- else ()
+ else()
add_test(SubDir ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/SubDir"
@@ -2056,7 +2078,7 @@ if(BUILD_TESTING)
"${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere"
"${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.o"
)
- endif ()
+ endif()
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDir")
if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC"))
@@ -2067,6 +2089,15 @@ if(BUILD_TESTING)
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
ADD_TEST_MACRO(PrecompiledHeader foo)
endif()
+
+ set(MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
+ if(CMAKE_Fortran_COMPILER)
+ list(APPEND MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_Fortran=1)
+ endif()
+ ADD_TEST_MACRO(MSVCDebugInformationFormat)
+ set_property(TEST MSVCDebugInformationFormat APPEND
+ PROPERTY LABELS "CUDA")
+
set(MSVCRuntimeLibrary_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
ADD_TEST_MACRO(MSVCRuntimeLibrary)
set_property(TEST MSVCRuntimeLibrary APPEND
@@ -2080,7 +2111,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(ModuleDefinition example_exe)
endif()
- if (CMAKE_C_COMPILER_ID MATCHES "Watcom" AND WIN32)
+ if(CMAKE_C_COMPILER_ID MATCHES "Watcom" AND WIN32)
ADD_TEST_MACRO(WatcomRuntimeLibrary)
endif()
@@ -2116,7 +2147,7 @@ if(BUILD_TESTING)
if(MSVC AND NOT MSVC_VERSION LESS 1310
AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio 9 "
OR CMAKE_SIZEOF_VOID_P EQUAL 4)
- AND (NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND (NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
)
ADD_TEST_MACRO(VSMASM VSMASM)
endif()
@@ -2128,7 +2159,7 @@ if(BUILD_TESTING)
if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 "
AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90"
- AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
ADD_TEST_MACRO(VSManagedCustomCommand)
endif()
@@ -2157,7 +2188,7 @@ if(BUILD_TESTING)
# The test (and tested property) works with .sln files, so it's skipped when:
# * cmake --build is set up to use MSBuild, since the MSBuild invocation does not use the .sln file
set(_last_test "")
- foreach(config ${CMAKE_CONFIGURATION_TYPES})
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
add_test(NAME VSExcludeFromDefaultBuild-${config} COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/VSExcludeFromDefaultBuild"
@@ -2295,7 +2326,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(VSNASM VSNASM)
endif()
- if (CMake_TEST_GreenHillsMULTI)
+ if(CMake_TEST_GreenHillsMULTI)
macro(add_test_GhsMulti test_name test_dir bin_sub_dir build_opts)
separate_arguments(_ghs_build_opts UNIX_COMMAND ${build_opts})
separate_arguments(_ghs_toolset_extra UNIX_COMMAND ${ghs_toolset_extra})
@@ -2356,7 +2387,7 @@ if(BUILD_TESTING)
set(ghs_config_name "__default__")
endif()
# test integrity build
- if (NOT ghs_skip_integrity AND (NOT ghs_target_platform OR ghs_target_platform MATCHES "integrity"))
+ if(NOT ghs_skip_integrity AND (NOT ghs_target_platform OR ghs_target_platform MATCHES "integrity"))
add_test_GhsMulti(integrityDDInt GhsMultiIntegrity/GhsMultiIntegrityDDInt "" "")
add_test_GhsMulti(integrityMonolith GhsMultiIntegrity/GhsMultiIntegrityMonolith "" "")
add_test_GhsMulti(integrityDD GhsMultiIntegrity/GhsMultiIntegrityDD "" "")
@@ -2412,9 +2443,6 @@ if(BUILD_TESTING)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSAndroid/${name}")
endmacro()
if(tegra AND NOT "${CMake_SOURCE_DIR};${CMake_BINARY_DIR}" MATCHES " ")
- if(vs10)
- add_test_VSAndroid(vs10 "Visual Studio 10 2010" "Tegra-Android")
- endif()
if(vs11)
add_test_VSAndroid(vs11 "Visual Studio 11 2012" "Tegra-Android")
endif()
@@ -2438,8 +2466,8 @@ if(BUILD_TESTING)
add_test_VSAndroid(vs17 "Visual Studio 17 2022" "ARM")
endif()
- if (APPLE)
- if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+ if(APPLE)
+ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(BundleTestInstallDir
"${CMake_BINARY_DIR}/Tests/BundleTest/InstallDirectory")
add_test(BundleTest ${CMAKE_CTEST_COMMAND}
@@ -2475,8 +2503,8 @@ if(BUILD_TESTING)
add_subdirectory(ObjC)
add_subdirectory(ObjCXX)
- endif ()
- endif ()
+ endif()
+ endif()
if(APPLE AND CTEST_TEST_CPACK)
add_test(BundleGeneratorTest ${CMAKE_CTEST_COMMAND}
@@ -2667,7 +2695,10 @@ if(BUILD_TESTING)
endif()
if(NOT DEFINED CMake_TEST_CTestUpdate_HG AND HG_EXECUTABLE
AND (UNIX OR NOT "${HG_EXECUTABLE}" MATCHES "cygwin"))
- set(CMake_TEST_CTestUpdate_HG 1)
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(HG_RV EQUAL 0)
+ set(CMake_TEST_CTestUpdate_HG 1)
+ endif()
endif()
if(CMake_TEST_CTestUpdate_HG)
if(NOT HG_EXECUTABLE)
@@ -3195,24 +3226,24 @@ if(BUILD_TESTING)
--output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log"
)
- if (CMAKE_TESTS_CDASH_SERVER)
+ if(CMAKE_TESTS_CDASH_SERVER)
set(regex "^([^:]+)://([^/]+)(.*)$")
- if ("${CMAKE_TESTS_CDASH_SERVER}" MATCHES "${regex}")
+ if("${CMAKE_TESTS_CDASH_SERVER}" MATCHES "${regex}")
set(protocol "${CMAKE_MATCH_1}")
set(server "${CMAKE_MATCH_2}")
set(path "${CMAKE_MATCH_3}")
- else ()
+ else()
set(protocol "http")
set(server "open.cdash.org")
set(path "")
message("warning: CMAKE_TESTS_CDASH_SERVER does not match expected regex...")
message(" ...using default url='${protocol}://${server}${path}' for CTestTest[23]")
- endif ()
- endif ()
+ endif()
+ endif()
- if (CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS AND CMAKE_TESTS_CDASH_SERVER)
+ if(CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS AND CMAKE_TESTS_CDASH_SERVER)
configure_file("${CMake_SOURCE_DIR}/Tests/CTestTest/test.cmake.in"
"${CMake_BINARY_DIR}/Tests/CTestTest/test.cmake" @ONLY ESCAPE_QUOTES)
add_test(CTestTest ${CMAKE_CTEST_COMMAND}
@@ -3254,19 +3285,19 @@ if(BUILD_TESTING)
# these tests take a long time, make sure they have it
# if timeouts have not already been set
get_test_property(CTestTest TIMEOUT PREVIOUS_TIMEOUT)
- if ("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
- set_tests_properties ( CTestTest
+ if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
+ set_tests_properties(CTestTest
PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
- endif ()
+ endif()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
get_test_property(CTestTest2 TIMEOUT PREVIOUS_TIMEOUT)
if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
- set_tests_properties ( CTestTest2
+ set_tests_properties(CTestTest2
PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
endif()
endif()
- endif ()
+ endif()
if(CMake_TEST_EXTERNAL_CMAKE)
set(CMAKE_SKIP_BOOTSTRAP_TEST 1)
@@ -3302,10 +3333,9 @@ if(BUILD_TESTING)
# provide more time for the bootstrap test
get_test_property(BootstrapTest TIMEOUT PREVIOUS_TIMEOUT)
- if ("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
- set_tests_properties ( BootstrapTest
- PROPERTIES TIMEOUT 5400)
- endif ()
+ if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
+ set_tests_properties(BootstrapTest PROPERTIES TIMEOUT 5400)
+ endif()
endif()
if(CMAKE_Fortran_COMPILER)
@@ -3369,56 +3399,70 @@ if(BUILD_TESTING)
set(JavaExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM})
ADD_TEST_MACRO(JavaExportImport JavaExportImport)
- get_filename_component(JNIPATH ${Java_JAVAC_EXECUTABLE} PATH)
+ get_filename_component(JAVACPATH ${Java_JAVAC_EXECUTABLE} REALPATH)
+ get_filename_component(JNIPATH ${JAVACPATH} PATH)
find_file(JNI_H jni.h
"${JNIPATH}/../include"
"${JNIPATH}/../java/include")
if(JNI_H AND EXISTS "${JNI_H}") # in case jni.h is a broken symlink
file(READ "${JNI_H}" JNI_FILE)
if("${JNI_FILE}" MATCHES "JDK1_2")
- add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/Java"
- "${CMake_BINARY_DIR}/Tests/JavaJar"
- ${build_generator_args}
- --build-project hello
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar")
- # For next tests, java tool must have same architecture as toolchain
- math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8")
execute_process(
COMMAND "${Java_JAVA_EXECUTABLE}" -version
OUTPUT_VARIABLE _version ERROR_VARIABLE _version RESULT_VARIABLE _result
)
- if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit")
- ## next test is valid only if Java version is less than 1.10
- if ("${Java_VERSION}" VERSION_LESS 1.10)
- add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/JavaJavah"
- "${CMake_BINARY_DIR}/Tests/JavaJavah"
- ${build_generator_args}
- --build-project helloJavah
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah")
+
+ # E2K has broken Java RVM before 3.5.2
+ if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "e2k" AND _result EQUAL 0)
+ string(REGEX MATCH "RVM ([0-9.]+)" RVMVER "${_version}")
+ # Consider empty match a broken version too
+ if("${CMAKE_MATCH_1}" VERSION_LESS "3.5.2")
+ set(BROKEN_RVM TRUE)
endif()
- ## next test is valid only if Java is, at least, version 1.8
- if (NOT "${Java_VERSION}" VERSION_LESS 1.8)
- add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders"
- "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders"
- ${build_generator_args}
- --build-project helloJavaNativeHeaders
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
- --build-target install
- --build-options
- "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
+ endif()
+
+ if(NOT BROKEN_RVM)
+ add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Java"
+ "${CMake_BINARY_DIR}/Tests/JavaJar"
+ ${build_generator_args}
+ --build-project hello
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar")
+
+ # For next tests, java tool must have same architecture as toolchain
+ math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8")
+ if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit")
+ ## next test is valid only if Java version is less than 1.10
+ if("${Java_VERSION}" VERSION_LESS 1.10)
+ add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/JavaJavah"
+ "${CMake_BINARY_DIR}/Tests/JavaJavah"
+ ${build_generator_args}
+ --build-project helloJavah
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah")
+ endif()
+ ## next test is valid only if Java is, at least, version 1.8
+ if(NOT "${Java_VERSION}" VERSION_LESS 1.8)
+ add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders"
+ "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders"
+ ${build_generator_args}
+ --build-project helloJavaNativeHeaders
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
+ --build-target install
+ --build-options
+ "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
+ endif()
endif()
endif()
endif()
@@ -3480,18 +3524,18 @@ if(BUILD_TESTING)
endif()
if(CMAKE_TEST_PLPLOT_DIR)
- add_test(plplot ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_PLPLOT_DIR}/../../EasyDashboardScripts/plplot.cmake )
+ add_test(plplot ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_PLPLOT_DIR}/../../EasyDashboardScripts/plplot.cmake)
set_tests_properties ( plplot PROPERTIES TIMEOUT 5400)
endif()
if(CMAKE_TEST_CHICKEN_DIR)
- add_test(Chicken ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_CHICKEN_DIR}/../../EasyDashboardScripts/Chicken.cmake )
- set_tests_properties ( Chicken PROPERTIES TIMEOUT 5400)
+ add_test(Chicken ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_CHICKEN_DIR}/../../EasyDashboardScripts/Chicken.cmake)
+ set_tests_properties(Chicken PROPERTIES TIMEOUT 5400)
endif()
if(CMAKE_TEST_KDELIBS_ALPHA_1_DIR)
- add_test(KDELibsAlpha1 ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_KDELIBS_ALPHA_1_DIR}/../../EasyDashboardScripts/kdelibs.cmake )
- set_tests_properties ( KDELibsAlpha1 PROPERTIES TIMEOUT 5400)
+ add_test(KDELibsAlpha1 ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_KDELIBS_ALPHA_1_DIR}/../../EasyDashboardScripts/kdelibs.cmake)
+ set_tests_properties(KDELibsAlpha1 PROPERTIES TIMEOUT 5400)
endif()
# Define a set of "contract" tests, each activated by a cache entry
@@ -3501,11 +3545,7 @@ if(BUILD_TESTING)
# The directory should also contain a Configure.cmake file that
# sets "CMake_TEST_CONTRACT_<project>_<var>" variables to configure
# the code below.
- foreach(project
- PLplot
- Trilinos
- VTK
- )
+ foreach(project IN ITEMS PLplot Trilinos VTK)
if(CMake_TEST_CONTRACT_${project})
include(Contracts/${project}/Configure.cmake)
ADD_TEST_MACRO(Contracts.${project} ${CMake_TEST_CONTRACT_${project}_RUN_TEST})
@@ -3578,6 +3618,14 @@ if(BUILD_TESTING)
add_subdirectory(CMakeGUI)
endif()
+ # Run CheckSourceTree as the very last test in the CMake/CTest/CPack test
+ # suite. It detects if any changes have been made to the CMake source tree
+ # by any previous configure, build or test steps.
+ if(GIT_EXECUTABLE AND EXISTS "${CMake_SOURCE_DIR}/.git"
+ AND NOT "${CMake_SOURCE_DIR}" STREQUAL "${CMake_BINARY_DIR}")
+ add_subdirectory(CheckSourceTree)
+ endif()
+
# If this is not an in-source build, provide a target to wipe out
# all the test build directories. This must come at the end after
# all the above logic has finished adding to TEST_BUILD_DIRS
diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
index 49a4041b2..0907d0381 100644
--- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
+++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
@@ -56,6 +56,15 @@ macro(check_version_string MODULE_NAME VERSION_VAR)
if (NOT _exclude_pos EQUAL -1)
message(STATUS "excluding check of ${VERSION_VAR}='${${VERSION_VAR}}' due to local configuration")
elseif (${MODULE_NAME}_FOUND)
+
+ unset(SKIP_CHECK)
+ if(${MODULE_NAME} STREQUAL "HG")
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(NOT HG_RV EQUAL 0)
+ message(WARNING "Broken HG executable detected, skipping")
+ set(SKIP_CHECK TRUE)
+ endif()
+ endif()
if (DEFINED ${VERSION_VAR})
message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'")
if (NOT ${VERSION_VAR} MATCHES "^[0-9]")
@@ -71,7 +80,9 @@ macro(check_version_string MODULE_NAME VERSION_VAR)
message(SEND_ERROR "unexpected: ${VERSION_VAR} is NOT VERSION_GREATER 0")
endif()
else()
- message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED")
+ if(NOT SKIP_CHECK)
+ message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED")
+ endif()
endif()
endif ()
endmacro()
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index 9e0b89101..bd2dd7e94 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -59,18 +59,3 @@ if(GIT_EXECUTABLE)
)
AddCMakeTest(PolicyCheck "${PolicyCheck_PreArgs}")
endif()
-
-# Run CheckSourceTree as the very last test in the CMake/CTest/CPack test
-# suite. It detects if any changes have been made to the CMake source tree
-# by any previous configure, build or test steps.
-#
-if(GIT_EXECUTABLE)
- string(REPLACE "\\" "/" ENV_HOME "$ENV{HOME}")
- set(CheckSourceTree_PreArgs
- "-DCMake_BINARY_DIR:PATH=${CMake_BINARY_DIR}"
- "-DCMake_SOURCE_DIR:PATH=${CMake_SOURCE_DIR}"
- "-DGIT_EXECUTABLE:STRING=${GIT_EXECUTABLE}"
- "-DHOME:STRING=${ENV_HOME}"
- )
- AddCMakeTest(CheckSourceTree "${CheckSourceTree_PreArgs}")
-endif()
diff --git a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in
deleted file mode 100644
index 4f2aaea9c..000000000
--- a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in
+++ /dev/null
@@ -1,365 +0,0 @@
-# Check the CMake source tree and report anything suspicious...
-#
-message("=============================================================================")
-message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
-message("")
-message("CMake_BINARY_DIR='${CMake_BINARY_DIR}'")
-message("CMake_SOURCE_DIR='${CMake_SOURCE_DIR}'")
-message("GIT_EXECUTABLE='${GIT_EXECUTABLE}'")
-message("HOME='${HOME}'")
-message("ENV{DASHBOARD_TEST_FROM_CTEST}='$ENV{DASHBOARD_TEST_FROM_CTEST}'")
-message("")
-string(REPLACE "\\" "\\\\" HOME "${HOME}")
-
-
-# Is the build directory the same as or underneath the source directory?
-# (i.e. - is it an "in source" build?)
-#
-set(in_source_build 0)
-set(build_under_source 0)
-
-string(FIND "${CMake_BINARY_DIR}" "${CMake_SOURCE_DIR}/" pos)
-if(pos EQUAL 0)
- message("build dir is *inside* source dir")
- set(build_under_source 1)
-elseif(CMake_SOURCE_DIR STREQUAL "${CMake_BINARY_DIR}")
- message("build dir *is* source dir")
- set(in_source_build 1)
-else()
- string(LENGTH "${CMake_SOURCE_DIR}" src_len)
- string(LENGTH "${CMake_BINARY_DIR}" bin_len)
-
- if(bin_len GREATER src_len)
- math(EXPR substr_len "${src_len}+1")
- string(SUBSTRING "${CMake_BINARY_DIR}" 0 ${substr_len} bin_dir)
- if(bin_dir STREQUAL "${CMake_SOURCE_DIR}/")
- message("build dir is under source dir")
- set(in_source_build 1)
- endif()
- endif()
-endif()
-
-message("src_len='${src_len}'")
-message("bin_len='${bin_len}'")
-message("substr_len='${substr_len}'")
-message("bin_dir='${bin_dir}'")
-message("in_source_build='${in_source_build}'")
-message("build_under_source='${build_under_source}'")
-message("")
-
-if(build_under_source)
- message(STATUS "Skipping rest of test because build tree is under source tree")
- return()
-endif()
-
-# If this does not appear to be a git checkout, just pass the test here
-# and now. (Do not let the test fail if it is run in a tree *exported* from a
-# repository or unpacked from a .zip file source installer...)
-#
-set(is_git_checkout 0)
-if(EXISTS "${CMake_SOURCE_DIR}/.git")
- set(is_git_checkout 1)
-endif()
-
-message("is_git_checkout='${is_git_checkout}'")
-message("")
-
-if(NOT is_git_checkout)
- message("source tree is not a git checkout... test passes by early return...")
- return()
-endif()
-
-# This test looks for the following types of changes in the source tree:
-#
-set(additions 0)
-set(conflicts 0)
-set(modifications 0)
-set(nonadditions 0)
-
-# ov == output variable... conditionally filled in by either git below:
-#
-set(cmd "")
-set(ov "")
-set(ev "")
-set(rv "")
-
-# If no GIT_EXECUTABLE, see if we can figure out which git was used
-# for the ctest_update step on this dashboard...
-#
-if(is_git_checkout AND NOT GIT_EXECUTABLE)
- set(ctest_ini_file "")
- set(exe "")
-
- # Use the old name:
- if(EXISTS "${CMake_BINARY_DIR}/DartConfiguration.tcl")
- set(ctest_ini_file "${CMake_BINARY_DIR}/DartConfiguration.tcl")
- endif()
-
- # But if it exists, prefer the new name:
- if(EXISTS "${CMake_BINARY_DIR}/CTestConfiguration.ini")
- set(ctest_ini_file "${CMake_BINARY_DIR}/CTestConfiguration.ini")
- endif()
-
- # If there is a ctest ini file, read the update command or git command
- # from it:
- #
- if(ctest_ini_file)
- file(STRINGS "${ctest_ini_file}" line REGEX "^GITCommand: (.*)$")
- string(REGEX REPLACE "^GITCommand: (.*)$" "\\1" line "${line}")
- if("${line}" MATCHES "^\"")
- string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}")
- else()
- string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}")
- endif()
- set(exe "${line}")
- if("${exe}" STREQUAL "GITCOMMAND-NOTFOUND")
- set(exe "")
- endif()
- if(exe)
- message("info: GIT_EXECUTABLE set by 'GITCommand:' from '${ctest_ini_file}'")
- endif()
-
- if(NOT exe)
- file(STRINGS "${ctest_ini_file}" line REGEX "^UpdateCommand: (.*)$")
- string(REGEX REPLACE "^UpdateCommand: (.*)$" "\\1" line "${line}")
- if("${line}" MATCHES "^\"")
- string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}")
- else()
- string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}")
- endif()
- set(exe "${line}")
- if("${exe}" STREQUAL "GITCOMMAND-NOTFOUND")
- set(exe "")
- endif()
- if(exe)
- message("info: GIT_EXECUTABLE set by 'UpdateCommand:' from '${ctest_ini_file}'")
- endif()
- endif()
- else()
- message("info: no DartConfiguration.tcl or CTestConfiguration.ini file...")
- endif()
-
- # If we have still not grokked the exe, look in the Update.xml file to see
- # if we can parse it from there...
- #
- if(NOT exe)
- file(GLOB_RECURSE update_xml_file "${CMake_BINARY_DIR}/Testing/Update.xml")
- if(update_xml_file)
- file(STRINGS "${update_xml_file}" line
- REGEX "^.*<UpdateCommand>(.*)</UpdateCommand>$" LIMIT_COUNT 1)
- string(REPLACE "&quot\;" "\"" line "${line}")
- string(REGEX REPLACE "^.*<UpdateCommand>(.*)</UpdateCommand>$" "\\1" line "${line}")
- if("${line}" MATCHES "^\"")
- string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}")
- else()
- string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}")
- endif()
- if(line)
- set(exe "${line}")
- endif()
- if(exe)
- message("info: GIT_EXECUTABLE set by '<UpdateCommand>' from '${update_xml_file}'")
- endif()
- else()
- message("info: no Update.xml file...")
- endif()
- endif()
-
- if(exe)
- set(GIT_EXECUTABLE "${exe}")
- message("GIT_EXECUTABLE='${GIT_EXECUTABLE}'")
- message("")
-
- if(NOT EXISTS "${GIT_EXECUTABLE}")
- message(FATAL_ERROR "GIT_EXECUTABLE does not exist...")
- endif()
- else()
- message(FATAL_ERROR "could not determine GIT_EXECUTABLE...")
- endif()
-endif()
-
-
-if(is_git_checkout AND GIT_EXECUTABLE)
- # Check with "git status" if there are any local modifications to the
- # CMake source tree:
- #
- message("=============================================================================")
- message("This is a git checkout, using git to verify source tree....")
- message("")
-
- execute_process(COMMAND ${GIT_EXECUTABLE} --version
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- OUTPUT_VARIABLE version_output
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- message("=== output of 'git --version' ===")
- message("${version_output}")
- message("=== end output ===")
- message("")
-
- execute_process(COMMAND ${GIT_EXECUTABLE} branch -a
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- OUTPUT_VARIABLE git_branch_output
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- message("=== output of 'git branch -a' ===")
- message("${git_branch_output}")
- message("=== end output ===")
- message("")
-
- execute_process(COMMAND ${GIT_EXECUTABLE} log -1
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- OUTPUT_VARIABLE git_log_output
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- message("=== output of 'git log -1' ===")
- message("${git_log_output}")
- message("=== end output ===")
- message("")
-
- message("Copy/paste this command to reproduce:")
- message("cd \"${CMake_SOURCE_DIR}\" && \"${GIT_EXECUTABLE}\" status")
- message("")
-
- set(cmd ${GIT_EXECUTABLE} status)
-endif()
-
-
-if(cmd)
- # Use the HOME value passed in to the script for calling git so it can
- # find its user/global config settings...
- #
- set(original_ENV_HOME "$ENV{HOME}")
- set(ENV{HOME} "${HOME}")
-
- execute_process(COMMAND ${cmd}
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- OUTPUT_VARIABLE ov
- ERROR_VARIABLE ev
- RESULT_VARIABLE rv)
-
- set(ENV{HOME} "${original_ENV_HOME}")
-
- message("Results of running ${cmd}")
- message("rv='${rv}'")
- message("ov='${ov}'")
- message("ev='${ev}'")
- message("")
-
- if(NOT rv STREQUAL 0)
- if(is_git_checkout AND (rv STREQUAL "1"))
- # Many builds of git return "1" from a "nothing is changed" git status call...
- # Do not fail with an error for rv==1 with git...
- else()
- message(FATAL_ERROR "error: ${cmd} attempt failed... (see output above)")
- endif()
- endif()
-else()
- message(FATAL_ERROR "error: no COMMAND to run to analyze source tree...")
-endif()
-
-
-# Analyze output:
-#
-if(NOT ov STREQUAL "")
- string(REPLACE ";" "\\\\;" lines "${ov}")
- string(REPLACE "\n" "E;" lines "${lines}")
-
- foreach(line ${lines})
- message("'${line}'")
-
- # But do not consider files that exist just because some user poked around
- # the file system with Windows Explorer or with the Finder from a Mac...
- # ('Thumbs.db' and '.DS_Store' files...)
- #
- set(consider 1)
- set(ignore_files_regex "^(. |.*(/|\\\\))(\\.DS_Store|Thumbs.db)E$")
- if(line MATCHES "${ignore_files_regex}")
- message(" line matches '${ignore_files_regex}' -- not considered")
- set(consider 0)
- endif()
-
- if(consider)
- if(is_git_checkout)
- if(line MATCHES "^#?[ \t]*modified:")
- message(" locally modified file detected...")
- set(modifications 1)
- endif()
-
- if(line MATCHES "^(# )?Untracked")
- message(" locally non-added file/directory detected...")
- set(nonadditions 1)
- endif()
- endif()
- endif()
- endforeach()
-endif()
-
-
-message("=============================================================================")
-message("additions='${additions}'")
-message("conflicts='${conflicts}'")
-message("modifications='${modifications}'")
-message("nonadditions='${nonadditions}'")
-message("")
-
-
-# Decide if the test passes or fails:
-#
-message("=============================================================================")
-
-if("$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
-
- # developers are allowed to have local additions and modifications...
- message("interactive test run")
- message("")
-
-else()
-
- message("dashboard test run")
- message("")
-
- # but dashboard machines are not allowed to have local additions or modifications...
- if(additions)
- message(FATAL_ERROR "test fails: local source tree additions")
- endif()
-
- if(modifications)
- message(FATAL_ERROR "test fails: local source tree modifications")
- endif()
-
- #
- # It's a dashboard run if ctest was run with '-D ExperimentalTest' or some
- # other -D arg on its command line or if ctest is running a -S script to run
- # a dashboard... Running ctest like that sets the DASHBOARD_TEST_FROM_CTEST
- # env var.
- #
-
-endif()
-
-
-# ...and nobody is allowed to have local non-additions or conflicts...
-# Not even developers.
-#
-if(nonadditions)
- if(in_source_build)
- message("
-warning: test results confounded because this is an 'in-source' build - cannot
-distinguish between non-added files that are in-source build products and
-non-added source files that somebody forgot to 'git add'... - this is only ok
-if this is intentionally an in-source dashboard build... Developers should
-use out-of-source builds to verify a clean source tree with this test...
-
-Allowing test to pass despite the warning message...
-")
- else()
- message(FATAL_ERROR "test fails: local source tree non-additions: use git add before committing, or remove the files from the source tree")
- endif()
-endif()
-
-if(conflicts)
- message(FATAL_ERROR "test fails: local source tree conflicts: resolve before committing")
-endif()
-
-
-# Still here? Good then...
-#
-message("test passes")
-message("")
diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
index 63c234acf..7acfcd911 100644
--- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
+++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
@@ -13,72 +13,84 @@ set(linux64_gcc_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-h
set(linux64_gcc_libs "gcc;gcc_s;c;gcc;gcc_s")
set(linux64_gcc_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
list(APPEND platforms linux64_gcc)
+list(APPEND langs C)
# g++ dummy.cxx -v
set(linux64_g++_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccalRBlq.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o")
set(linux64_g++_libs "stdc++;m;gcc_s;gcc;c;gcc_s;gcc")
set(linux64_g++_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
list(APPEND platforms linux64_g++)
+list(APPEND langs CXX)
# f95 dummy.f -v
set(linux64_f95_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccAVcN7N.o -lgfortranbegin -lgfortran -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o")
set(linux64_f95_libs "gfortranbegin;gfortran;m;gcc_s;gcc;c;gcc_s;gcc")
set(linux64_f95_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
list(APPEND platforms linux64_f95)
+list(APPEND langs Fortran)
# suncc dummy.c '-#'
set(linux64_suncc_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xa.o dummy.o -Y \"/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64\" -Qy -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o")
set(linux64_suncc_libs "c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a")
set(linux64_suncc_dirs "/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64")
list(APPEND platforms linux64_suncc)
+list(APPEND langs C)
# sunCC dummy.cxx -v
set(linux64_sunCC_text "/opt/sun/sunstudio12/prod/lib/amd64/ld -u __1cH__CimplKcplus_init6F_v_ --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -R/opt/sun/sunstudio12/lib/rw7/amd64:/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/lib/rtlibs/amd64:/opt/SUNWspro/lib/amd64:/lib64:/usr/lib64 -o a.out /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/CCrti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o -Y P,/opt/sun/sunstudio12/lib/rw7/amd64:/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/sunstudio12/prod/lib/rw7/amd64:/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64 dummy.o -lCstd -lCrun -lm -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/CCrtn.o /opt/sun/sunstudio12/prod/lib/amd64/crtn.o >&/tmp/ld.04973.2.err")
set(linux64_sunCC_libs "Cstd;Crun;m;c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a")
set(linux64_sunCC_dirs "/opt/sun/sunstudio12/lib/rw7/amd64;/opt/sun/sunstudio12/lib/amd64;/opt/sun/sunstudio12/rtlibs/amd64;/opt/sun/sunstudio12/prod/lib/rw7/amd64;/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64")
list(APPEND platforms linux64_sunCC)
+list(APPEND langs CXX)
# sunf90 dummy.f -v
set(linux64_sunf90_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -R/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/lib/rtlibs/amd64 -o a.out /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xi.o -Y P,/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64 dummy.o -lfui -lfai -lfsu -Bdynamic -lmtsk -lpthread -lm -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o")
set(linux64_sunf90_libs "fui;fai;fsu;mtsk;pthread;m;c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a")
set(linux64_sunf90_dirs "/opt/sun/sunstudio12/lib/amd64;/opt/sun/sunstudio12/rtlibs/amd64;/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64")
list(APPEND platforms linux64_sunf90)
+list(APPEND langs Fortran)
# icc dummy.c -v
set(linux64_icc_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/iccBP8OfN.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o")
set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c")
set(linux64_icc_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
list(APPEND platforms linux64_icc)
+list(APPEND langs C)
# icxx dummy.cxx -v
set(linux64_icxx_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/icpc270GoT.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -Bdynamic -lstdc++ -Bstatic -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o")
set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c")
set(linux64_icxx_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
list(APPEND platforms linux64_icxx)
+list(APPEND langs CXX)
# ifort dummy.f -v
set(linux64_ifort_text "ld --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/intel/compiler/11.0/lib/intel64/for_main.o dum.cxx -Bstatic -lifport -lifcore -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -lirc -Bdynamic -lpthread -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o")
set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;gcc_s;gcc;irc_s;dl;c")
set(linux64_ifort_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
list(APPEND platforms linux64_ifort)
+list(APPEND langs Fortran)
# pgcc dummy.c -v
set(linux64_pgcc_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgcc7OscXa5ur7Zk.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o")
set(linux64_pgcc_libs "nspgc;pgc;m;gcc;c;gcc")
set(linux64_pgcc_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
list(APPEND platforms linux64_pgcc)
+list(APPEND langs C)
# pgCC dummy.cxx -v
set(linux64_pgCC_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgCCFhjcDt1fs1Ki.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lstd -lC -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o")
set(linux64_pgCC_libs "std;C;nspgc;pgc;m;gcc;c;gcc")
set(linux64_pgCC_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
list(APPEND platforms linux64_pgCC)
+list(APPEND langs CXX)
# pgf90 dummy.f -v
set(linux64_pgf90_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/pgi/linux86-64/8.0-3/lib/f90main.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgf90QOIc_eB9xY5h.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl -lnspgc -lpgc -lrt -lpthread -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o")
set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;gcc;c;gcc")
set(linux64_pgf90_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
list(APPEND platforms linux64_pgf90)
+list(APPEND langs Fortran)
# nagfor dummy.f -Wl,-v
set(linux64_nagfor_text " /usr/libexec/gcc/x86_64-redhat-linux/4.4.5/collect2 --no-add-needed --eh-frame-hdr --build-id -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../.. /usr/local/NAG/lib/f90_init.o /usr/local/NAG/lib/quickfit.o dummy.o -rpath /usr/local/NAG/lib /usr/local/NAG/lib/libf53.so /usr/local/NAG/lib/libf53.a -lm -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crtn.o")
@@ -86,6 +98,7 @@ set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickf
set(linux64_nagfor_dirs "/usr/lib/gcc/x86_64-redhat-linux/4.4.5;/usr/lib64;/lib64;/usr/lib")
set(linux64_nagfor_obj_regex "^/usr/local/NAG/lib")
list(APPEND platforms linux64_nagfor)
+list(APPEND langs Fortran)
# absoft dummy.f -X -v
set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF)
@@ -93,6 +106,7 @@ set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF)
set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;gcc;gcc_s;c;gcc;gcc_s")
set(linux64_absoft_dirs "/opt/absoft11.1/lib64;/usr/lib/gcc/x86_64-linux-gnu/4.4.5;/usr/lib;/lib")
list(APPEND platforms linux64_absoft)
+list(APPEND langs Fortran)
# gcc dummy.c -v # in strange path
set(linux64_test1_text "
@@ -101,12 +115,14 @@ ${linux64_gcc_text}")
set(linux64_test1_libs "${linux64_gcc_libs}")
set(linux64_test1_dirs "${linux64_gcc_dirs}")
list(APPEND platforms linux64_test1)
+list(APPEND langs C)
# sunCC dummy.cxx -v # extra slashes
set(linux64_test2_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/sun/sunstudio12/prod/lib/amd64//crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xa.o dummy.o -Y \"/opt/sun/sunstudio12/prod/lib//amd64:/lib64:/usr//lib64\" -Qy -lc /opt/sun/sunstudio12/prod/lib/amd64//libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o")
set(linux64_test2_libs "c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a")
set(linux64_test2_dirs "/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64")
list(APPEND platforms linux64_test2)
+list(APPEND langs CXX)
# -specs=redhat-hardened-ld
set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-hardened-ld' '-v' '-O2' '-g' '-pipe' '-Wall' '-Werror=format-security' '-fexceptions' '-fstack-protector-strong' '--param' 'ssp-buffer-size=4' '-grecord-gcc-switches' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-m64' '-mtune=generic' '-I' '/usr/lib64/gfortran/modules' '-o' 'a.out' '-rdynamic' '-shared-libgcc' '-march=x86-64' '-pie'
@@ -114,12 +130,14 @@ set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-h
set(linux64_test3_libs "gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc")
set(linux64_test3_dirs "/usr/lib/gcc/x86_64-redhat-linux/5.1.1;/usr/lib64;/lib64;/usr/lib")
list(APPEND platforms linux64_test3)
+list(APPEND langs Fortran)
# clang -fsanitize=memory
set(linux64_clang_sanitize_memory_text [[ "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../.. -L/usr/lib/llvm-3.8/bin/../lib -L/lib -L/usr/lib -whole-archive /usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a -no-whole-archive --dynamic-list=/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a.syms /tmp/dummy-27898d.o --no-as-needed -lpthread -lrt -lm -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crtn.o]])
set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;gcc;gcc_s;c;gcc;gcc_s")
set(linux64_clang_sanitize_memory_dirs "/usr/lib/gcc/x86_64-linux-gnu/5.4.0;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-3.8/lib;/lib")
list(APPEND platforms linux64_clang_sanitize_memory)
+list(APPEND langs C)
#-----------------------------------------------------------------------------
# Mac
@@ -144,12 +162,14 @@ set(mac_i686_gcc_Wlv_libs "gcc")
set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
list(APPEND platforms mac_i686_gcc_Wlv)
+list(APPEND langs C)
# gcc -arch i686 dummy.c -v
set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem")
set(mac_i686_gcc_libs "gcc")
set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
list(APPEND platforms mac_i686_gcc)
+list(APPEND langs C)
# g++ -arch i686 dummy.cxx -v -Wl,-v
set(mac_i686_g++_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem
@@ -171,12 +191,14 @@ set(mac_i686_g++_Wlv_libs "stdc++;gcc")
set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
list(APPEND platforms mac_i686_g++_Wlv)
+list(APPEND langs CXX)
# g++ -arch i686 dummy.cxx -v
set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem")
set(mac_i686_g++_libs "stdc++;gcc")
set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
list(APPEND platforms mac_i686_g++)
+list(APPEND langs CXX)
# gfortran dummy.f -v -Wl,-v
set(mac_i686_gfortran_Wlv_text " /usr/local/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem
@@ -195,12 +217,14 @@ set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc")
set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib")
set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
list(APPEND platforms mac_i686_gfortran_Wlv)
+list(APPEND langs Fortran)
# gfortran dummy.f -v
set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem")
set(mac_i686_gfortran_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc")
set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib")
list(APPEND platforms mac_i686_gfortran)
+list(APPEND langs Fortran)
# gcc -arch ppc dummy.c -v -Wl,-v
set(mac_ppc_gcc_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem
@@ -222,12 +246,14 @@ set(mac_ppc_gcc_Wlv_libs "gcc")
set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
list(APPEND platforms mac_ppc_gcc_Wlv)
+list(APPEND langs C)
# gcc -arch ppc dummy.c -v
set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem")
set(mac_ppc_gcc_libs "gcc")
set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib")
list(APPEND platforms mac_ppc_gcc)
+list(APPEND langs C)
# g++ -arch ppc dummy.cxx -v -Wl,-v
set(mac_ppc_g++_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem
@@ -249,12 +275,14 @@ set(mac_ppc_g++_Wlv_libs "stdc++;gcc")
set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
list(APPEND platforms mac_ppc_g++_Wlv)
+list(APPEND langs CXX)
# g++ -arch ppc dummy.cxx -v
set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemStubs -lSystem")
set(mac_ppc_g++_libs "stdc++;gcc")
set(mac_ppc_g++_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib")
list(APPEND platforms mac_ppc_g++)
+list(APPEND langs CXX)
# absoft dummy.f -X -v
set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin)
@@ -263,12 +291,14 @@ set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin
set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;gcc")
set(mac_absoft_dirs "/Applications/Absoft11.1/lib;/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
list(APPEND platforms mac_absoft)
+list(APPEND langs Fortran)
# Xcode 8.3: clang++ dummy.cpp -v
set(mac_clang_v_text " \"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld\" -demangle -lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o a.out /var/folders/hc/95l7dhnx459c57g4yg_6yd8c0000gp/T/dummy-384ea1.o -lc++ -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.1.0/lib/darwin/libclang_rt.osx.a")
set(mac_clang_v_libs "c++")
set(mac_clang_v_dirs "")
list(APPEND platforms mac_clang_v)
+list(APPEND langs CXX)
#-----------------------------------------------------------------------------
# Sun
@@ -278,24 +308,28 @@ set(sun_cc_text "/usr/ccs/bin/ld /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/pro
set(sun_cc_libs "c")
set(sun_cc_dirs "/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib")
list(APPEND platforms sun_cc)
+list(APPEND langs C)
# CC dummy.cxx -v
set(sun_CC_text "/usr/ccs/bin/ld -u __1cH__CimplKcplus_init6F_v_ -zld32=-S/opt/SUNWspro/prod/lib/libldstab_ws.so -zld64=-S/opt/SUNWspro/prod/lib/v9/libldstab_ws.so -zld32=-S/opt/SUNWspro/prod/lib/libCCexcept.so.1 -zld64=-S/opt/SUNWspro/prod/lib/v9/libCCexcept.so.1 -R/opt/SUNWspro/lib/rw7:/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib:/usr/ccs/lib:/lib:/usr/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/CCrti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xa.o -Y P,/opt/SUNWspro/lib/rw7:/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/rw7:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -lCstd -lCrun -lm -lc /opt/SUNWspro/prod/lib/CCrtn.o /opt/SUNWspro/prod/lib/crtn.o >&/tmp/ld.14846.2.err")
set(sun_CC_libs "Cstd;Crun;m;c")
set(sun_CC_dirs "/opt/SUNWspro/lib/rw7;/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/rw7;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib")
list(APPEND platforms sun_CC)
+list(APPEND langs CXX)
# f77 dummy.f -v
set(sun_f77_text "/usr/ccs/bin/ld -t -R/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xi.o -Y P,/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -lf77compat -zallextract -lompstubs -zdefaultextract -lfui -lfai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfsu -lsunmath -lm -lc /opt/SUNWspro/prod/lib/crtn.o")
set(sun_f77_libs "f77compat;-zallextract;ompstubs;-zdefaultextract;fui;fai;fai2;fsumai;fprodai;fminlai;fmaxlai;fminvai;fmaxvai;fsu;sunmath;m;c")
set(sun_f77_dirs "/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib")
list(APPEND platforms sun_f77)
+list(APPEND langs Fortran)
# f90 dummy.f -v
set(sun_f90_text "/usr/ccs/bin/ld -t -R/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xi.o -Y P,/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -zallextract -lompstubs -zdefaultextract -lfui -lfai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfsu -lsunmath -lm -lc /opt/SUNWspro/prod/lib/crtn.o")
set(sun_f90_libs "-zallextract;ompstubs;-zdefaultextract;fui;fai;fai2;fsumai;fprodai;fminlai;fmaxlai;fminvai;fmaxvai;fsu;sunmath;m;c")
set(sun_f90_dirs "/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib")
list(APPEND platforms sun_f90)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# AIX
@@ -305,12 +339,14 @@ set(aix_xlc_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 du
set(aix_xlc_32_libs "xlopt;xl;c")
set(aix_xlc_32_dirs "/usr/vac/lib")
list(APPEND platforms aix_xlc_32)
+list(APPEND langs C)
# xlc -q64 dummy.c -V
set(aix_xlc_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 dummy.o -L/usr/vac/lib -lxlopt -lxl -lc")
set(aix_xlc_64_libs "xlopt;xl;c")
set(aix_xlc_64_dirs "/usr/vac/lib")
list(APPEND platforms aix_xlc_64)
+list(APPEND langs C)
# xlC -q32 dummy.cxx -V
set(aix_xlC_32_text "
@@ -319,6 +355,7 @@ set(aix_xlC_32_text "
set(aix_xlC_32_libs "xlopt;xl;C;m;c")
set(aix_xlC_32_dirs "/usr/vac/lib;/usr/vacpp/lib")
list(APPEND platforms aix_xlC_32)
+list(APPEND langs CXX)
# xlC -q64 dummy.cxx -V
set(aix_xlC_64_text "
@@ -327,36 +364,42 @@ set(aix_xlC_64_text "
set(aix_xlC_64_libs "xlopt;xl;C;m;c")
set(aix_xlC_64_dirs "/usr/vac/lib;/usr/vacpp/lib")
list(APPEND platforms aix_xlC_64)
+list(APPEND langs CXX)
# xlf -q32 dummy.f -V
set(aix_xlf_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 -bh:4 -bh:4 -bh:4 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc")
set(aix_xlf_32_libs "xlf90;xlopt;xlf;xlomp_ser;m;c")
set(aix_xlf_32_dirs "/usr/lpp/xlf/lib")
list(APPEND platforms aix_xlf_32)
+list(APPEND langs Fortran)
# xlf -q64 dummy.f -V
set(aix_xlf_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 -bh:4 -bh:4 -bh:4 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc")
set(aix_xlf_64_libs "xlf90;xlopt;xlf;xlomp_ser;m;c")
set(aix_xlf_64_dirs "/usr/lpp/xlf/lib")
list(APPEND platforms aix_xlf_64)
+list(APPEND langs Fortran)
# xlf90 -q32 dummy.f -V
set(aix_xlf90_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc")
set(aix_xlf90_32_libs "xlf90;xlopt;xlf;xlomp_ser;m;c")
set(aix_xlf90_32_dirs "/usr/lpp/xlf/lib")
list(APPEND platforms aix_xlf90_32)
+list(APPEND langs Fortran)
# xlf90 -q64 dummy.f -V
set(aix_xlf90_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc")
set(aix_xlf90_64_libs "xlf90;xlopt;xlf;xlomp_ser;m;c")
set(aix_xlf90_64_dirs "/usr/lpp/xlf/lib")
list(APPEND platforms aix_xlf90_64)
+list(APPEND langs Fortran)
# g++ dummy.c -v
set(aix_g++_text " /prefix/libexec/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/collect2 -bpT:0x10000000 -bpD:0x20000000 -btextro /lib/crt0.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtcxa.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtdbase.o -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0 -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/../../.. /tmp//ccKROJ1f.o -lstdc++ -lm -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a -lc -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a")
set(aix_g++_libs "stdc++;m;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a;c;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a")
set(aix_g++_dirs "/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0;/prefix/lib")
list(APPEND platforms aix_g++)
+list(APPEND langs CXX)
#-----------------------------------------------------------------------------
# HP
@@ -367,6 +410,7 @@ set(hp_cc_old_text "cc: LPATH is /usr/lib/pa1.1:/usr/lib:/opt/langtools/lib:
set(hp_cc_old_libs "c")
set(hp_cc_old_dirs "/usr/lib/pa1.1;/usr/lib;/opt/langtools/lib")
list(APPEND platforms hp_cc_old)
+list(APPEND langs C)
# aCC dummy.cxx -v
set(hp_aCC_old_text "LPATH=/usr/lib/pa1.1:/usr/lib:/opt/langtools/lib
@@ -374,6 +418,7 @@ set(hp_aCC_old_text "LPATH=/usr/lib/pa1.1:/usr/lib:/opt/langtools/lib
set(hp_aCC_old_libs "std;stream;Csup;m;cl;c")
set(hp_aCC_old_dirs "/usr/lib/pa1.1;/usr/lib;/opt/langtools/lib;/opt/aCC/lib")
list(APPEND platforms hp_aCC_old)
+list(APPEND langs CXX)
# cc dummy.c -v
set(hp_cc_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32
@@ -381,6 +426,7 @@ set(hp_cc_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32
set(hp_cc_32_libs "c")
set(hp_cc_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32")
list(APPEND platforms hp_cc_32)
+list(APPEND langs C)
# cc +DD64 dummy.c -v
set(hp_cc_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64
@@ -388,6 +434,7 @@ set(hp_cc_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64
set(hp_cc_64_libs "c")
set(hp_cc_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64")
list(APPEND platforms hp_cc_64)
+list(APPEND langs C)
# aCC dummy.cxx -v
set(hp_aCC_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32
@@ -395,6 +442,7 @@ set(hp_aCC_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32
set(hp_aCC_32_libs "std_v2;Csup;m;unwind;Csup;c;dl")
set(hp_aCC_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32;/opt/aCC/lib/hpux32")
list(APPEND platforms hp_aCC_32)
+list(APPEND langs CXX)
# aCC +DD64 dummy.cxx -v
set(hp_aCC_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64
@@ -402,6 +450,7 @@ set(hp_aCC_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64
set(hp_aCC_64_libs "std_v2;Csup;m;unwind;Csup;c;dl")
set(hp_aCC_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64;/opt/aCC/lib/hpux64")
list(APPEND platforms hp_aCC_64)
+list(APPEND langs CXX)
# f90 dummy.f -v
set(hp_f90_32_text "LPATH is: /usr/lib/hpux32/:/opt/langtools/lib/hpux32/
@@ -409,6 +458,7 @@ set(hp_f90_32_text "LPATH is: /usr/lib/hpux32/:/opt/langtools/lib/hpux32/
set(hp_f90_32_libs "-l:libF90.a;-l:libIO77.a;m;c;unwind;uca")
set(hp_f90_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32")
list(APPEND platforms hp_f90_32)
+list(APPEND langs Fortran)
# f90 +DD64 dummy.f -v
set(hp_f90_64_text "LPATH is: /usr/lib/hpux64/:/opt/langtools/lib/hpux64/
@@ -416,6 +466,7 @@ set(hp_f90_64_text "LPATH is: /usr/lib/hpux64/:/opt/langtools/lib/hpux64/
set(hp_f90_64_libs "-l:libF90.a;-l:libIO77.a;m;c;unwind;uca")
set(hp_f90_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64")
list(APPEND platforms hp_f90_64)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# Cygwin
@@ -425,12 +476,14 @@ set(cygwin_gcc_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic -
set(cygwin_gcc_libs "gcc;cygwin;user32;kernel32;advapi32;shell32;gcc")
set(cygwin_gcc_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib")
list(APPEND platforms cygwin_gcc)
+list(APPEND langs C)
# g++ dummy.cxx -v
set(cygwin_g++_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc")
set(cygwin_g++_libs "stdc++;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc")
set(cygwin_g++_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib")
list(APPEND platforms cygwin_g++)
+list(APPEND langs CXX)
# gfortran dummy.f -v
set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe
@@ -439,6 +492,7 @@ set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe
set(cygwin_gfortran_libs "gfortranbegin;gfortran;gcc_s;gcc_s;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc_s;gcc_s;gcc")
set(cygwin_gfortran_dirs "/usr/lib/gcc/i686-pc-cygwin/4.3.2;/usr/lib")
list(APPEND platforms cygwin_gfortran)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# MSYS
@@ -448,18 +502,21 @@ set(msys_gcc_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe
set(msys_gcc_libs "mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
set(msys_gcc_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
list(APPEND platforms msys_gcc)
+list(APPEND langs C)
# g++ dummy.cxx -v
set(msys_g++_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cci5hYPk.o -lstdc++ -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o")
set(msys_g++_libs "stdc++;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
set(msys_g++_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
list(APPEND platforms msys_g++)
+list(APPEND langs CXX)
# g77 dummy.f -v
set(msys_g77_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/ccabRxQ1.o -lfrtbegin -lg2c -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o")
set(msys_g77_libs "frtbegin;g2c;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
list(APPEND platforms msys_g77)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# MSYS2-runtime
@@ -469,18 +526,21 @@ set(msys2rt_gcc_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --
set(msys2rt_gcc_libs "msys-2.0;user32;kernel32;advapi32;shell32")
set(msys2rt_gcc_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib")
list(APPEND platforms msysrt_gcc)
+list(APPEND langs C)
# g++ dummy.cxx -v
set(msys2rt_g++_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc")
set(msys2rt_g++_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32")
set(msys2rt_g++_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib")
list(APPEND platforms msysrt_g++)
+list(APPEND langs CXX)
# g77 dummy.f -v
set(msys2rt_g77_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- -u ___register_frame_info -u ___deregister_frame_info /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o /usr/lib/gcc/i686-pc-msys/6.4.0/crtbegin.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccqRWKWg.o -lgfortranbegin -lgfortran -lgcc_s -lgcc_s -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc_s -lgcc_s -lgcc /usr/lib/gcc/i686-pc-msys/6.4.0/crtend.o")
set(msys2rt_g77_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32")
set(msys2rt_g77_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib")
list(APPEND platforms msysrt_g77)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# MSYS2-mingw
@@ -490,18 +550,21 @@ set(msys2_gcc_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/c
set(msys2_gcc_libs "mingw32;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc;moldname;mingwex")
set(msys2_gcc_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib")
list(APPEND platforms msys2_gcc)
+list(APPEND langs C)
# g++ dummy.cxx -v
set(msys2_g++_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe -plugin-opt=-fresolution=C:/msys64/tmp/ccJQgvbN.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../.. C:/msys64/tmp/ccqPpuVS.o -lstdc++ -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtend.o")
set(msys2_g++_libs "stdc++;mingw32;gcc_s;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex")
set(msys2_g++_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib")
list(APPEND platforms msys2_g++)
+list(APPEND langs CXX)
# gfortran dummy.f90 -v
set(msys2_gfortran_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe -plugin-opt=-fresolution=C:/msys64/tmp/cczOKIDy.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../.. C:/msys64/tmp/ccyXuCgD.o -lgfortran -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lquadmath -lm -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtend.o")
set(msys2_gfortran_libs "gfortran;mingw32;gcc_s;gcc;moldname;mingwex;quadmath;m;mingw32;gcc_s;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex")
set(msys2_gfortran_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib")
list(APPEND platforms msys2_gfortran)
+list(APPEND langs Fortran)
#-----------------------------------------------------------------------------
# MSVC from NVIDIA CUDA
@@ -510,6 +573,18 @@ set(nvcc_msvc_text [[cuda-fake-ld cl.exe -nologo "tmp/a_dlink.obj" "tmp/CMakeCUD
set(nvcc_msvc_libs "cudadevrt.lib;cudart_static.lib")
set(nvcc_msvc_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64")
list(APPEND platforms nvcc_msvc)
+list(APPEND langs CUDA)
+
+#-----------------------------------------------------------------------------
+# MSVC from NVIDIA CUDA custom compiler
+
+set(nvcc_msvc_cl_text [[cuda-fake-ld cl -nologo "tmp/a_dlink.obj" "tmp/CMakeCUDACompilerId.obj" -link -INCREMENTAL:NO "/LIBPATH:C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/../lib/x64" cudadevrt.lib cudart_static.lib -Fe"a.exe"]])
+set(nvcc_msvc_cl_libs "cudadevrt.lib;cudart_static.lib")
+set(nvcc_msvc_cl_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64")
+set(nvcc_msvc_cl_compiler_id NVIDIA)
+set(nvcc_msvc_cl_compiler_sim_id MSVC)
+list(APPEND platforms nvcc_msvc_cl)
+list(APPEND langs CUDA)
#-----------------------------------------------------------------------------
# PGI on Windows
@@ -527,6 +602,7 @@ set(windows_pgf95_startfile "pgimain[mx][xpt]+[.]obj")
set(windows_pgf95_libs "libpgmp;pg;libpgf90rtl;libpgf90;libpgf90_rpm1;libpgf902;libpgf90rtl;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
set(windows_pgf95_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
list(APPEND platforms windows_pgf95)
+list(APPEND langs Fortran)
# pgf77 dummy.f77 -v
set(windows_pgf77_text [[Writing to file C:\temp\pgf776eC42buYRoCNJk.lnk
@@ -537,6 +613,7 @@ set(windows_pgf77_startfile "pgimain[mx][xpt]+[.]obj")
set(windows_pgf77_libs "libpgmp;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
set(windows_pgf77_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
list(APPEND platforms windows_pgf77)
+list(APPEND langs Fortran)
# pgcc dummy.c -v
set(windows_pgcc_text [[Writing to file C:\temp\pgcc6esqW26_ZNKyL.lnk
@@ -547,6 +624,7 @@ set(windows_pgcc_startfile "pgimain[mx][xpt]+[.]obj")
set(windows_pgcc_libs "libpgmp;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
set(windows_pgcc_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
list(APPEND platforms windows_pgcc)
+list(APPEND langs C)
endif()
@@ -554,13 +632,20 @@ endif()
# Test parsing for all above examples.
set(CMAKE_LINKER "not-a-linker[]().*+^$?")
-foreach(p IN LISTS platforms)
+foreach(p lang IN ZIP_LISTS platforms langs)
if(DEFINED ${p}_startfile)
set(CMAKE_LINK_STARTFILE "${${p}_startfile}")
else()
unset(CMAKE_LINK_STARTFILE)
endif()
- cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}")
+ if(DEFINED ${p}_compiler_id)
+ set(CMAKE_${lang}_ID ${${p}_compiler_id})
+ endif()
+ if(DEFINED ${p}_compiler_sim_id)
+ set(CMAKE_${lang}_SIMULATE_ID ${${p}_compiler_sim_id})
+ endif()
+
+ cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}" LANGUAGE ${lang})
foreach(v libs dirs fwks)
if(DEFINED "${p}_${v}" AND NOT "${${v}}" STREQUAL "${${p}_${v}}")
diff --git a/Tests/CTestCoverageCollectGCOV/test.cmake.in b/Tests/CTestCoverageCollectGCOV/test.cmake.in
index a36f3743b..7c7a3e5bb 100644
--- a/Tests/CTestCoverageCollectGCOV/test.cmake.in
+++ b/Tests/CTestCoverageCollectGCOV/test.cmake.in
@@ -34,9 +34,10 @@ set(expected_out
# then back to relative to get them in canonical form (or maybe this is a bug
# in how the tarball is generated?)
function(to_relative_paths real_paths paths)
+ file(REAL_PATH "${CTEST_BINARY_DIRECTORY}" base)
foreach(file ${paths})
- file(REAL_PATH "${file}" real_path BASE_DIRECTORY "${CTEST_BINARY_DIRECTORY}")
- file(RELATIVE_PATH relative_path "${CTEST_BINARY_DIRECTORY}" "${real_path}")
+ file(REAL_PATH "${file}" real_path BASE_DIRECTORY "${base}")
+ file(RELATIVE_PATH relative_path "${base}" "${real_path}")
list(APPEND local_real_paths "${relative_path}")
message(DEBUG "${file} -> ${real_path} -> ${relative_path}")
endforeach()
diff --git a/Tests/CTestTestFdSetSize/sleep.c b/Tests/CTestTestFdSetSize/sleep.c
index 2fb6490aa..d55cec661 100644
--- a/Tests/CTestTestFdSetSize/sleep.c
+++ b/Tests/CTestTestFdSetSize/sleep.c
@@ -1,7 +1,11 @@
#if defined(_WIN32)
# include <windows.h>
-#else
+#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE)
# include <unistd.h>
+#else
+# include <time.h>
+
+# include <sys/select.h>
#endif
/* sleeps for 0.1 second */
@@ -9,8 +13,14 @@ int main(int argc, char** argv)
{
#if defined(_WIN32)
Sleep(100);
-#else
+#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE)
usleep(100 * 1000);
+#else
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+
+ select(0, NULL, NULL, NULL, &tv);
#endif
return 0;
}
diff --git a/Tests/CTestUpdateCommon.cmake b/Tests/CTestUpdateCommon.cmake
index 0f8ec8e27..467b41a35 100644
--- a/Tests/CTestUpdateCommon.cmake
+++ b/Tests/CTestUpdateCommon.cmake
@@ -73,7 +73,7 @@ function(check_updates build)
string(REGEX REPLACE "${rev_regex}" "\\1" element "${r}")
set(element_${element} 1)
endforeach()
- foreach(element ${rev_elements})
+ foreach(element IN LISTS rev_elements)
if(NOT element_${element})
list(APPEND MISSING "global <${element}> element")
endif()
@@ -85,7 +85,7 @@ function(check_updates build)
if(MISSING)
# List the missing entries
string(APPEND MSG "Update.xml is missing expected entries:\n")
- foreach(f ${MISSING})
+ foreach(f IN LISTS MISSING)
string(APPEND MSG " ${f}\n")
endforeach()
else()
@@ -97,7 +97,7 @@ function(check_updates build)
if(EXTRA)
# List the extra entries
string(APPEND MSG "Update.xml has extra unexpected entries:\n")
- foreach(f ${EXTRA})
+ foreach(f IN LISTS EXTRA)
string(APPEND MSG " ${f}\n")
endforeach()
else()
diff --git a/Tests/CTestUpdateP4.cmake.in b/Tests/CTestUpdateP4.cmake.in
index 8a99e67f0..2ac01e271 100644
--- a/Tests/CTestUpdateP4.cmake.in
+++ b/Tests/CTestUpdateP4.cmake.in
@@ -109,7 +109,7 @@ list(APPEND P4CMD ${P4_CLIENT})
message("Adding files to repository")
file(GLOB_RECURSE files ${TOP}/user-source/*)
-foreach(filename ${files})
+foreach(filename IN LISTS files)
run_child(
WORKING_DIRECTORY ${TOP}/user-source
COMMAND ${P4CMD} add ${filename}
@@ -140,14 +140,14 @@ run_child(
# Make changes in the working tree.
message("Changing content...")
update_content(user-source files_added files_removed dirs_added)
-foreach(filename ${files_added})
+foreach(filename IN LISTS files_added)
message("add: ${filename}")
run_child(
WORKING_DIRECTORY ${TOP}/user-source
COMMAND ${P4CMD} add ${TOP}/user-source/${filename}
)
endforeach()
-foreach(filename ${files_removed})
+foreach(filename IN LISTS files_removed)
run_child(
WORKING_DIRECTORY ${TOP}/user-source
COMMAND ${P4CMD} delete ${TOP}/user-source/${filename}
diff --git a/Tests/CheckSourceTree/CMakeLists.txt b/Tests/CheckSourceTree/CMakeLists.txt
new file mode 100644
index 000000000..3abc6a924
--- /dev/null
+++ b/Tests/CheckSourceTree/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_test(NAME CMake.CheckSourceTree
+ COMMAND ${CMAKE_CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE}
+ -D CMake_SOURCE_DIR=${CMake_SOURCE_DIR}
+ -P ${CMAKE_CURRENT_LIST_DIR}/check.cmake
+ )
+set_property(TEST CMake.CheckSourceTree PROPERTY RUN_SERIAL 1)
diff --git a/Tests/CheckSourceTree/check.cmake b/Tests/CheckSourceTree/check.cmake
new file mode 100644
index 000000000..c2e3529d6
--- /dev/null
+++ b/Tests/CheckSourceTree/check.cmake
@@ -0,0 +1,22 @@
+# Give Git access to the real home directory to get user's settings.
+if(DEFINED ENV{CTEST_REAL_HOME})
+ set(ENV{HOME} "$ENV{CTEST_REAL_HOME}")
+endif()
+
+execute_process(
+ COMMAND "${GIT_EXECUTABLE}" status
+ WORKING_DIRECTORY "${CMake_SOURCE_DIR}"
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+ RESULT_VARIABLE result
+ )
+string(REPLACE "\n" "\n " output " ${output}")
+if(NOT result EQUAL 0)
+ message(FATAL_ERROR "'git status' failed (${result}):\n${output}")
+endif()
+
+if(output MATCHES "\n[ \t#]*(Changes |new file:|modified:|Untracked )")
+ message(FATAL_ERROR "The source tree is not clean. 'git status' reports:\n${output}")
+endif()
+
+message(STATUS "The source tree is clean.")
diff --git a/Tests/CheckSwift.cmake b/Tests/CheckSwift.cmake
index fcbae7ef9..099c298ee 100644
--- a/Tests/CheckSwift.cmake
+++ b/Tests/CheckSwift.cmake
@@ -14,6 +14,7 @@ if(NOT DEFINED CMAKE_Swift_COMPILER)
project(CheckSwift Swift)
file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
\"set(CMAKE_Swift_COMPILER \\\"\${CMAKE_Swift_COMPILER}\\\")\\n\"
+ \"set(CMAKE_Swift_COMPILER_VERSION \\\"\${CMAKE_Swift_COMPILER_VERSION}\\\")\\n\"
\"set(CMAKE_Swift_FLAGS \\\"\${CMAKE_Swift_FLAGS}\\\")\\n\")
")
@@ -54,6 +55,7 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
message(STATUS "${_desc} - ${CMAKE_Swift_COMPILER}")
set(CMAKE_Swift_COMPILER "${CMAKE_Swift_COMPILER}" CACHE FILEPATH "Swift compiler")
+ set(CMAKE_Swift_COMPILER_VERSION "${CMAKE_Swift_COMPILER_VERSION}" CACHE FILEPATH "Swift compiler version")
set(CMAKE_Swift_FLAGS "${CMAKE_Swift_FLAGS}" CACHE STRING "Swift flags")
mark_as_advanced(CMAKE_Swift_COMPILER)
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index c6d1e8a05..f3d3a73f1 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -356,6 +356,7 @@ else()
HAVE_CXX_STD_17=$<COMPILE_FEATURES:cxx_std_17>
HAVE_CXX_STD_20=$<COMPILE_FEATURES:cxx_std_20>
HAVE_CXX_STD_23=$<COMPILE_FEATURES:cxx_std_23>
+ HAVE_CXX_STD_26=$<COMPILE_FEATURES:cxx_std_26>
)
endif()
diff --git a/Tests/CompileFeatures/genex_test.cpp b/Tests/CompileFeatures/genex_test.cpp
index 9c3910e03..048f3decd 100644
--- a/Tests/CompileFeatures/genex_test.cpp
+++ b/Tests/CompileFeatures/genex_test.cpp
@@ -27,6 +27,9 @@
# if HAVE_CXX_STD_23 && !defined(ALLOW_LATER_STANDARDS)
# error HAVE_CXX_STD_23 is true with CXX_STANDARD == 11
# endif
+# if HAVE_CXX_STD_26 && !defined(ALLOW_LATER_STANDARDS)
+# error HAVE_CXX_STD_26 is true with CXX_STANDARD == 11
+# endif
#endif
#if !HAVE_OVERRIDE_CONTROL
diff --git a/Tests/Complex/CMakeLists.txt b/Tests/Complex/CMakeLists.txt
index 5df22d25f..9493a2fa4 100644
--- a/Tests/Complex/CMakeLists.txt
+++ b/Tests/Complex/CMakeLists.txt
@@ -5,6 +5,14 @@ cmake_minimum_required(VERSION 2.4)
cmake_policy(SET CMP0054 NEW)
project (Complex)
+# Inform the test if the debug configuration is getting built.
+string(APPEND CMAKE_C_FLAGS_RELEASE " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG")
+
# Test that renaming a built-in works when configured multiple times.
message("message")
function(message)
diff --git a/Tests/Complex/Executable/complex.cxx b/Tests/Complex/Executable/complex.cxx
index 49e97d585..67a164521 100644
--- a/Tests/Complex/Executable/complex.cxx
+++ b/Tests/Complex/Executable/complex.cxx
@@ -62,7 +62,7 @@ void cmPassed(const char* Message, const char* m2 = "")
# error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
#endif
-#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
+#if defined(COMPLEX_NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
# error Per-configuration directory-level definition not inherited.
#endif
diff --git a/Tests/ComplexOneConfig/CMakeLists.txt b/Tests/ComplexOneConfig/CMakeLists.txt
index 5a4134d21..e4fdc6833 100644
--- a/Tests/ComplexOneConfig/CMakeLists.txt
+++ b/Tests/ComplexOneConfig/CMakeLists.txt
@@ -5,6 +5,14 @@ cmake_minimum_required(VERSION 2.4)
cmake_policy(SET CMP0054 NEW)
project (Complex)
+# Inform the test if the debug configuration is getting built.
+string(APPEND CMAKE_C_FLAGS_RELEASE " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG")
+
# Try setting a new policy. The IF test is for coverage.
if(POLICY CMP0003)
cmake_policy(SET CMP0003 NEW)
diff --git a/Tests/ComplexOneConfig/Executable/complex.cxx b/Tests/ComplexOneConfig/Executable/complex.cxx
index 54c18f4ab..097668bbf 100644
--- a/Tests/ComplexOneConfig/Executable/complex.cxx
+++ b/Tests/ComplexOneConfig/Executable/complex.cxx
@@ -62,7 +62,7 @@ void cmPassed(const char* Message, const char* m2 = "")
# error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
#endif
-#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
+#if defined(COMPLEX_NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
# error Per-configuration directory-level definition not inherited.
#endif
diff --git a/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt
index 97670e392..447e137d4 100644
--- a/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt
+++ b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt
@@ -1,3 +1,6 @@
-project(SeparableCompCXXOnly LANGUAGES CXX CUDA)
+# Set CMAKE_CUDA_SEPARABLE_COMPILATION before `project`
+# so we verify that compiler/linker verbose extraction
+# works as required when a `dlink` is part of it
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
+project(SeparableCompCXXOnly LANGUAGES CXX CUDA)
add_executable(SeparableCompCXXOnly main.cpp)
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index aa4755d30..39634ac87 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -7,13 +7,13 @@ endmacro ()
add_cuda_test_macro(CudaOnly.Architecture Architecture)
add_cuda_test_macro(CudaOnly.ArchSpecial CudaOnlyArchSpecial)
add_cuda_test_macro(CudaOnly.CompileFlags CudaOnlyCompileFlags)
-
add_cuda_test_macro(CudaOnly.EnableStandard CudaOnlyEnableStandard)
add_cuda_test_macro(CudaOnly.ExportPTX CudaOnlyExportPTX)
add_cuda_test_macro(CudaOnly.SharedRuntimePlusToolkit CudaOnlySharedRuntimePlusToolkit)
add_cuda_test_macro(CudaOnly.Standard98 CudaOnlyStandard98)
add_cuda_test_macro(CudaOnly.Toolkit CudaOnlyToolkit)
add_cuda_test_macro(CudaOnly.ToolkitBeforeLang CudaOnlyToolkitBeforeLang)
+add_cuda_test_macro(CudaOnly.ToolkitMultipleDirs CudaOnlyToolkitMultipleDirs)
add_cuda_test_macro(CudaOnly.WithDefs CudaOnlyWithDefs)
add_cuda_test_macro(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine)
add_cuda_test_macro(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
@@ -28,6 +28,19 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang")
add_cuda_test_macro(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag)
endif()
+# The CUDA only ships the shared version of the toolkit libraries
+# on windows
+if(NOT WIN32)
+ add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit)
+endif()
+
+add_cuda_test_macro(CudaOnly.DeviceLTO CudaOnlyDeviceLTO)
+
+if(MSVC)
+ # Tests for features that only work with MSVC
+ add_cuda_test_macro(CudaOnly.PDB CudaOnlyPDB)
+endif()
+
add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
@@ -41,16 +54,6 @@ add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND
set_property(TEST "CudaOnly.DontResolveDeviceSymbols" APPEND
PROPERTY LABELS "CUDA")
-# The CUDA only ships the shared version of the toolkit libraries
-# on windows
-if(NOT WIN32)
- add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit)
-endif()
-
-if(MSVC)
- add_cuda_test_macro(CudaOnly.PDB CudaOnlyPDB)
-endif()
-
add_test(NAME CudaOnly.RuntimeControls COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
diff --git a/Tests/CudaOnly/DeviceLTO/CMakeLists.txt b/Tests/CudaOnly/DeviceLTO/CMakeLists.txt
new file mode 100644
index 000000000..653b35db7
--- /dev/null
+++ b/Tests/CudaOnly/DeviceLTO/CMakeLists.txt
@@ -0,0 +1,37 @@
+cmake_minimum_required(VERSION 3.18)
+project(DeviceLTO CUDA)
+
+# Goal:
+# Verify that we correctly compile with device LTO
+# Verify that device LTO requirements are propagated to
+# the final device link line
+
+add_library(CUDA_dlto STATIC file1.cu file2.cu file3.cu)
+add_executable(CudaOnlyDeviceLTO main.cu)
+
+set_target_properties(CUDA_dlto
+ PROPERTIES
+ CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES_ALL}"
+ CUDA_SEPARABLE_COMPILATION ON
+ POSITION_INDEPENDENT_CODE ON)
+
+set_target_properties(CudaOnlyDeviceLTO
+ PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON
+ CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES_ALL}"
+ )
+
+target_link_libraries(CudaOnlyDeviceLTO PRIVATE CUDA_dlto)
+
+include(CheckIPOSupported)
+check_ipo_supported(LANGUAGES CUDA RESULT ipo_supported)
+if(ipo_supported)
+ set_target_properties(CUDA_dlto
+ PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION ON)
+
+ # When non-LTO variants (i.e. virtual) are built together with LTO ones the
+ # linker warns about missing device LTO for the virtual architectures.
+ # Ignore these warnings.
+ target_link_options(CudaOnlyDeviceLTO PRIVATE "$<DEVICE_LINK:-w>")
+endif()
diff --git a/Tests/CudaOnly/DeviceLTO/file1.cu b/Tests/CudaOnly/DeviceLTO/file1.cu
new file mode 100644
index 000000000..703927cfd
--- /dev/null
+++ b/Tests/CudaOnly/DeviceLTO/file1.cu
@@ -0,0 +1,17 @@
+#ifdef _WIN32
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+extern __device__ int file2_func(int);
+void __global__ kernel(int x)
+{
+ file2_func(x);
+}
+
+EXPORT int launch_kernel(int x)
+{
+ kernel<<<1, 1>>>(x);
+ return x;
+}
diff --git a/Tests/CudaOnly/DeviceLTO/file2.cu b/Tests/CudaOnly/DeviceLTO/file2.cu
new file mode 100644
index 000000000..73d646819
--- /dev/null
+++ b/Tests/CudaOnly/DeviceLTO/file2.cu
@@ -0,0 +1,5 @@
+extern __device__ int file3_func(int);
+int __device__ file2_func(int x)
+{
+ return x + file3_func(x);
+}
diff --git a/Tests/CudaOnly/DeviceLTO/file3.cu b/Tests/CudaOnly/DeviceLTO/file3.cu
new file mode 100644
index 000000000..235ac0665
--- /dev/null
+++ b/Tests/CudaOnly/DeviceLTO/file3.cu
@@ -0,0 +1,4 @@
+int __device__ file3_func(int x)
+{
+ return x * x * x;
+}
diff --git a/Tests/CudaOnly/DeviceLTO/main.cu b/Tests/CudaOnly/DeviceLTO/main.cu
new file mode 100644
index 000000000..8ef487338
--- /dev/null
+++ b/Tests/CudaOnly/DeviceLTO/main.cu
@@ -0,0 +1,62 @@
+#include <iostream>
+
+#include "cuda.h"
+
+#ifdef _WIN32
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+IMPORT int launch_kernel(int x);
+
+int choose_cuda_device()
+{
+ int nDevices = 0;
+ cudaError_t err = cudaGetDeviceCount(&nDevices);
+ if (err != cudaSuccess) {
+ std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+ << std::endl;
+ return 1;
+ }
+ for (int i = 0; i < nDevices; ++i) {
+ cudaDeviceProp prop;
+ cudaError_t err = cudaGetDeviceProperties(&prop, i);
+ if (err != cudaSuccess) {
+ std::cerr << "Could not retrieve properties from CUDA device " << i
+ << std::endl;
+ return 1;
+ }
+ std::cout << "prop.major: " << prop.major << std::endl;
+ err = cudaSetDevice(i);
+ if (err != cudaSuccess) {
+ std::cout << "Could not select CUDA device " << i << std::endl;
+ } else {
+ return 0;
+ }
+ }
+
+ std::cout << "Could not find a CUDA enabled card" << std::endl;
+
+ return 1;
+}
+
+int main()
+{
+ int ret = choose_cuda_device();
+ if (ret) {
+ return 0;
+ }
+
+ cudaError_t err;
+ launch_kernel(1);
+ err = cudaGetLastError();
+ if (err != cudaSuccess) {
+ std::cerr << "launch_kernel: kernel launch should have passed.\n "
+ "Error message: "
+ << cudaGetErrorString(err) << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/Tests/CudaOnly/ToolkitMultipleDirs/CMakeLists.txt b/Tests/CudaOnly/ToolkitMultipleDirs/CMakeLists.txt
new file mode 100644
index 000000000..92551499d
--- /dev/null
+++ b/Tests/CudaOnly/ToolkitMultipleDirs/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.15)
+project(CudaOnlyToolkitMultipleDirs CUDA)
+
+find_package(CUDAToolkit REQUIRED)
+
+add_subdirectory(subdir)
+
+if(NOT DEFINED CUDAToolkit_VERSION)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDAToolkit_VERSION not found")
+endif()
+
+message(STATUS "CUDAToolkit_VERSION: ${CUDAToolkit_VERSION}")
+message(STATUS "CUDAToolkit_VERSION_MAJOR: ${CUDAToolkit_VERSION_MAJOR}")
+message(STATUS "CUDAToolkit_VERSION_MINOR: ${CUDAToolkit_VERSION_MINOR}")
+message(STATUS "CUDAToolkit_VERSION_PATCH: ${CUDAToolkit_VERSION_PATCH}")
+message(STATUS "CUDAToolkit_BIN_DIR: ${CUDAToolkit_BIN_DIR}")
+message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}")
+message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}")
+message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}")
+
+add_executable(CudaOnlyToolkitMultipleDirs main.cu)
+target_link_libraries(CudaOnlyToolkitMultipleDirs PRIVATE CUDA::toolkit)
diff --git a/Tests/CudaOnly/ToolkitMultipleDirs/main.cu b/Tests/CudaOnly/ToolkitMultipleDirs/main.cu
new file mode 100644
index 000000000..0f3ccdcc8
--- /dev/null
+++ b/Tests/CudaOnly/ToolkitMultipleDirs/main.cu
@@ -0,0 +1,8 @@
+// Only thing we care about is that these headers are found
+#include <cuda.h>
+#include <cuda_runtime_api.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/Tests/CudaOnly/ToolkitMultipleDirs/subdir/CMakeLists.txt b/Tests/CudaOnly/ToolkitMultipleDirs/subdir/CMakeLists.txt
new file mode 100644
index 000000000..f1f4b8925
--- /dev/null
+++ b/Tests/CudaOnly/ToolkitMultipleDirs/subdir/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+find_package(CUDAToolkit REQUIRED)
diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in
index 7c6f76a24..7722d7d5f 100644
--- a/Tests/EnforceConfig.cmake.in
+++ b/Tests/EnforceConfig.cmake.in
@@ -10,7 +10,7 @@ if(NOT CTEST_CONFIGURATION_TYPE)
set(CTEST_CMD "@CMAKE_CTEST_COMMAND@@CMAKE_EXECUTABLE_SUFFIX@")
get_filename_component(CTEST_DIR "${CTEST_CMD}" PATH)
get_filename_component(CTEST_EXE "${CTEST_CMD}" NAME)
- foreach(cfg Release Debug MinSizeRel RelWithDebInfo)
+ foreach(cfg IN ITEMS Release Debug MinSizeRel RelWithDebInfo)
if(NOT CTEST_CONFIGURATION_TYPE)
if(EXISTS "${CTEST_DIR}/${cfg}/${CTEST_EXE}")
set(CTEST_CONFIGURATION_TYPE ${cfg})
@@ -36,4 +36,4 @@ unset(ENV{CMAKE_GENERATOR_TOOLSET})
unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS})
@TEST_HOME_ENV_CODE@
-@TEST_WARN_VS10_CODE@
+@TEST_WARN_VS11_CODE@
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index c9e41f564..6f19c13c0 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -155,6 +155,15 @@ target_include_directories(testInterfaceIncludeUser
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>"
)
set_property(TARGET testInterfaceIncludeUser PROPERTY IMPORTED_NO_SYSTEM 1)
+
+add_library(testInterfaceIncludeUser2 INTERFACE)
+target_include_directories(testInterfaceIncludeUser2
+ INTERFACE
+ "$<INSTALL_INTERFACE:include/testInterfaceIncludeUser>"
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>"
+)
+set_property(TARGET testInterfaceIncludeUser2 PROPERTY EXPORT_NO_SYSTEM 1)
+
install(
FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser/testInterfaceInclude.h"
@@ -562,6 +571,7 @@ install(
TopDirLib SubDirLinkA
systemlib
testInterfaceIncludeUser
+ testInterfaceIncludeUser2
EXPORT exp
RUNTIME DESTINATION $<1:bin>$<0:/wrong>
LIBRARY DESTINATION $<1:lib>$<0:/wrong> NAMELINK_SKIP
@@ -622,6 +632,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
TopDirLib SubDirLinkA
systemlib
testInterfaceIncludeUser
+ testInterfaceIncludeUser2
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 272c7a95b..5bafdf825 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -75,6 +75,10 @@ add_library(imp_testInterfaceInclude1 STATIC imp_testInterfaceInclude1.c)
target_include_directories(imp_testInterfaceInclude1 SYSTEM PRIVATE testInterfaceIncludeSystem)
target_link_libraries(imp_testInterfaceInclude1 PRIVATE exp_testInterfaceIncludeUser)
+add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1b PRIVATE exp_testInterfaceIncludeUser2)
+
add_executable(imp_UseSharedLibWithHelper1 ../../../InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c)
target_link_libraries(imp_UseSharedLibWithHelper1 PRIVATE exp_testSharedLibWithHelper testSharedLibHelperExclude)
@@ -122,9 +126,13 @@ target_link_libraries(imp_testExe1b
bld_testStaticLibWithPlugin
)
-add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c)
-target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem)
-target_link_libraries(imp_testInterfaceInclude1b PRIVATE bld_testInterfaceIncludeUser)
+add_library(imp_testInterfaceInclude1c STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1c SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1c PRIVATE bld_testInterfaceIncludeUser)
+
+add_library(imp_testInterfaceInclude1d STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1d SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1d PRIVATE bld_testInterfaceIncludeUser2)
add_custom_target(check_testLib1_genex ALL
COMMAND ${CMAKE_COMMAND} -DtestLib1=$<TARGET_FILE:exp_testLib1>
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index e4c6c66ac..81d31e77b 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -45,7 +45,11 @@ if(NOT DEFINED EP_TEST_HG OR EP_TEST_HG)
find_package(Hg)
endif()
if(NOT DEFINED EP_TEST_HG AND Hg_FOUND)
- set(EP_TEST_HG 1)
+ # Check if hg executable is working
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(HG_RV EQUAL 0)
+ set(EP_TEST_HG 1)
+ endif()
endif()
message(STATUS "EP_TEST_CVS='${EP_TEST_CVS}' CVS_EXECUTABLE='${CVS_EXECUTABLE}'")
diff --git a/Tests/FindOpenAL/CMakeLists.txt b/Tests/FindOpenAL/CMakeLists.txt
new file mode 100644
index 000000000..fc4803e2c
--- /dev/null
+++ b/Tests/FindOpenAL/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindOpenAL.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindOpenAL/Test"
+ "${CMake_BINARY_DIR}/Tests/FindOpenAL/Test"
+ ${build_generator_args}
+ --build-project TestFindOpenAL
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindOpenAL/Test/CMakeLists.txt b/Tests/FindOpenAL/Test/CMakeLists.txt
new file mode 100644
index 000000000..fa3e2638e
--- /dev/null
+++ b/Tests/FindOpenAL/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.21)
+project(TestFindOpenAL CXX)
+include(CTest)
+
+find_package(OpenAL REQUIRED)
+
+add_executable(test_tgt main.cxx)
+target_link_libraries(test_tgt OpenAL::OpenAL)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.cxx)
+target_include_directories(test_var PRIVATE ${OPENAL_INCLUDE_DIR})
+target_link_libraries(test_var PRIVATE ${OPENAL_LIBRARY})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindOpenAL/Test/main.cxx b/Tests/FindOpenAL/Test/main.cxx
new file mode 100644
index 000000000..bb45faf5b
--- /dev/null
+++ b/Tests/FindOpenAL/Test/main.cxx
@@ -0,0 +1,13 @@
+#include <AL/al.h>
+#include <AL/alc.h>
+#include <stdio.h>
+
+int main()
+{
+ /* Reference an AL symbol without requiring a context at runtime. */
+ printf("&alGetString = %p\n", &alGetString);
+
+ /* Reference an ALC symbol without requiring a context at runtime. */
+ printf("&alcGetString = %p\n", &alcGetString);
+ return 0;
+}
diff --git a/Tests/FindOpenSP/CMakeLists.txt b/Tests/FindOpenSP/CMakeLists.txt
new file mode 100644
index 000000000..26826d3f0
--- /dev/null
+++ b/Tests/FindOpenSP/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindOpenSP.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindOpenSP/Test"
+ "${CMake_BINARY_DIR}/Tests/FindOpenSP/Test"
+ ${build_generator_args}
+ --build-project TestFindOpenSP
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindOpenSP/Test/CMakeLists.txt b/Tests/FindOpenSP/Test/CMakeLists.txt
new file mode 100644
index 000000000..d8992d9af
--- /dev/null
+++ b/Tests/FindOpenSP/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.4)
+project(TestFindOpenSP CXX)
+include(CTest)
+
+find_package(OpenSP REQUIRED)
+
+add_definitions(-DSP_MULTI_BYTE="${OpenSP_MULTI_BYTE}")
+
+add_executable(test_tgt main.cxx)
+target_link_libraries(test_tgt OpenSP::OpenSP)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.cxx)
+target_include_directories(test_var PRIVATE ${OpenSP_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${OpenSP_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindOpenSP/Test/main.cxx b/Tests/FindOpenSP/Test/main.cxx
new file mode 100644
index 000000000..ef8aa2c4e
--- /dev/null
+++ b/Tests/FindOpenSP/Test/main.cxx
@@ -0,0 +1,55 @@
+#include <cassert>
+#include <string>
+
+#include "ParserEventGeneratorKit.h"
+
+std::string CharStringtostring(const SGMLApplication::CharString source)
+{
+ // The CharString type might have multi-byte characters if SP_MULTI_BYTE was
+ // defined
+ std::string result;
+ result.resize(source.len);
+ for (size_t i = 0; i < source.len; i++) {
+ result[i] = static_cast<char>(source.ptr[i]);
+ }
+ return result;
+}
+
+class OutlineApplication : public SGMLApplication
+{
+public:
+ OutlineApplication()
+ : depth_(0)
+ {
+ }
+ void startElement(const StartElementEvent& event)
+ {
+ for (unsigned i = 0; i < depth_; i++)
+ parsedOutput += "\t";
+ parsedOutput += CharStringtostring(event.gi);
+ depth_++;
+ }
+ void endElement(const EndElementEvent&) { depth_--; }
+ std::string parsedOutput;
+
+private:
+ unsigned depth_;
+};
+
+int main()
+{
+ std::string expectedOutput = "TESTDOC\tTESTELEMENT";
+ char file_name[] = "test.sgml";
+ char* files[] = { file_name, 0 };
+
+ ParserEventGeneratorKit parserKit;
+ EventGenerator* egp = parserKit.makeEventGenerator(1, files);
+ OutlineApplication app;
+ unsigned nErrors = egp->run(app);
+
+ assert(nErrors == 0);
+ assert(app.parsedOutput.compare(expectedOutput) == 0);
+
+ delete egp;
+ return 0;
+}
diff --git a/Tests/FindOpenSP/Test/test.sgml b/Tests/FindOpenSP/Test/test.sgml
new file mode 100644
index 000000000..bbf0da6ae
--- /dev/null
+++ b/Tests/FindOpenSP/Test/test.sgml
@@ -0,0 +1,7 @@
+ <!DOCTYPE TESTDOC [
+<!ELEMENT TESTDOC - - (TESTELEMENT)+>
+<!ELEMENT TESTELEMENT - - (#PCDATA)>
+]>
+<TESTDOC>
+<TESTELEMENT>Hello</TESTELEMENT>
+</TESTDOC>
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index c25b2c304..e4143b940 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -20,7 +20,7 @@ find_package(OpenGL QUIET)
find_package(NotAPackage QUIET)
# Look for a package that has an advanced find module.
-find_package(VTK QUIET)
+find_package(Boost QUIET)
add_executable(FindPackageTest FindPackageTest.cxx)
diff --git a/Tests/FindVulkan/Test/CMakeLists.txt b/Tests/FindVulkan/Test/CMakeLists.txt
index 42543ac6f..dfcfc156a 100644
--- a/Tests/FindVulkan/Test/CMakeLists.txt
+++ b/Tests/FindVulkan/Test/CMakeLists.txt
@@ -7,7 +7,10 @@ set(components
glslang
shaderc_combined
SPIRV-Tools
+ volk
+ dxc
)
+
if(APPLE)
list(APPEND components MoltenVK)
endif()
@@ -75,6 +78,14 @@ if(APPLE)
add_test(NAME test_tgt_MoltenVK COMMAND test_tgt_MoltenVK)
endif()
+add_executable(test_tgt_volk main-volk.cxx)
+target_link_libraries(test_tgt_volk Vulkan::volk)
+add_test(NAME test_tgt_volk COMMAND test_tgt_volk)
+
+add_executable(test_tgt_dxc_lib main-dxc_lib.cxx)
+target_link_libraries(test_tgt_dxc_lib Vulkan::dxc_lib)
+add_test(NAME test_tgt_dxc_lib COMMAND test_tgt_dxc_lib)
+
if(Vulkan_GLSLC_EXECUTABLE)
add_test(NAME test_glslc
COMMAND ${CMAKE_COMMAND}
@@ -92,3 +103,12 @@ if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
-P "${CMAKE_CURRENT_LIST_DIR}/Run-glslangValidator.cmake"
)
endif()
+
+if(Vulkan_dxc_EXECUTABLE)
+ add_test(NAME test_dxc_exe
+ COMMAND ${CMAKE_COMMAND}
+ "-DVULKAN_DXC_EXECUTABLE=${Vulkan_dxc_EXECUTABLE}"
+ "-DVULKAN_DXC_EXECUTABLE_TARGET=$<TARGET_FILE:Vulkan::dxc_exe>"
+ -P "${CMAKE_CURRENT_LIST_DIR}/Run-dxc_exe.cmake"
+ )
+endif()
diff --git a/Tests/FindVulkan/Test/Run-dxc_exe.cmake b/Tests/FindVulkan/Test/Run-dxc_exe.cmake
new file mode 100644
index 000000000..0d38855ee
--- /dev/null
+++ b/Tests/FindVulkan/Test/Run-dxc_exe.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.12)
+
+function(run_dxc_exe exe exe_display)
+ execute_process(COMMAND ${exe} --help
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE result
+ )
+
+ if(NOT result EQUAL 0)
+ message(SEND_ERROR "Result of ${exe_display} --help is ${result}, should be 0")
+ endif()
+
+ if(NOT output MATCHES "^OVERVIEW: HLSL Compiler for ")
+ message(SEND_ERROR "Output of ${exe_display} --help is \"${output}\", should begin with \"OVERVIEW: HLSL Compiler for \"")
+ endif()
+endfunction()
+
+run_dxc_exe("${VULKAN_DXC_EXECUTABLE}" "\${VULKAN_DXC_EXECUTABLE}")
+run_dxc_exe("${VULKAN_DXC_EXECUTABLE_TARGET}" "Vulkan::dxc_exe")
diff --git a/Tests/FindVulkan/Test/main-dxc_lib.cxx b/Tests/FindVulkan/Test/main-dxc_lib.cxx
new file mode 100644
index 000000000..6ccb0dea0
--- /dev/null
+++ b/Tests/FindVulkan/Test/main-dxc_lib.cxx
@@ -0,0 +1,23 @@
+#include <cstdio>
+
+#include "dxc/dxcapi.h"
+#include "printf.h"
+
+int main()
+{
+ IDxcCompiler3* compiler;
+ DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
+
+ assert(compiler);
+
+ IDxcVersionInfo* version;
+ compiler->QueryInterface(&version);
+
+ uint32_t major, minor;
+ version->GetVersion(&major, &minor);
+ printf("DirectX Shader Compiler: %u.%u\n", major, minor);
+ version->Release();
+ compiler->Release();
+
+ return 0;
+}
diff --git a/Tests/FindVulkan/Test/main-volk.cxx b/Tests/FindVulkan/Test/main-volk.cxx
new file mode 100644
index 000000000..2ec9fb48b
--- /dev/null
+++ b/Tests/FindVulkan/Test/main-volk.cxx
@@ -0,0 +1,14 @@
+#include <iostream>
+
+#include <volk/volk.h>
+
+int main()
+{
+ if (volkInitialize() != VK_SUCCESS) {
+ std::cout << "volk initialization success!" << std::endl;
+ } else {
+ std::cout << "volk initialization failure!" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/Tests/FortranModules/Submodules/CMakeLists.txt b/Tests/FortranModules/Submodules/CMakeLists.txt
index ab8e0f9e5..783af7e1a 100644
--- a/Tests/FortranModules/Submodules/CMakeLists.txt
+++ b/Tests/FortranModules/Submodules/CMakeLists.txt
@@ -16,6 +16,7 @@
add_executable(submod
main.f90
parent.f90
+ obfuscated_parent.f90
child.f90
grandchild.f90
greatgrandchild.f90
diff --git a/Tests/FortranModules/Submodules/main.f90 b/Tests/FortranModules/Submodules/main.f90
index 3cd29892c..67ffba877 100644
--- a/Tests/FortranModules/Submodules/main.f90
+++ b/Tests/FortranModules/Submodules/main.f90
@@ -1,7 +1,10 @@
program main
use parent, only : child_function,grandchild_subroutine
use parent, only : sibling_function,GreatGrandChild_subroutine
+ ! Using a module without postfix
+ use obfuscated_parent
implicit none
- if (child_function()) call grandchild_subroutine
- if (sibling_function()) call GreatGrandChild_subroutine
+ if (child_function()) call grandchild_subroutine
+ if (sibling_function()) call GreatGrandChild_subroutine
+ if (child_function_obf()) call grandchild_subroutine_obf
end program
diff --git a/Tests/FortranModules/Submodules/obfuscated_parent.f90 b/Tests/FortranModules/Submodules/obfuscated_parent.f90
new file mode 100644
index 000000000..f3e68be1e
--- /dev/null
+++ b/Tests/FortranModules/Submodules/obfuscated_parent.f90
@@ -0,0 +1,33 @@
+! This module has two procedures from the "parent" module
+! but it has different combinations 'module <word>' phrases
+! in breaked lines for test of modules dependencies detection
+
+! Module declaration on breaked line with reminder
+module &
+ obfuscated_parent; implicit none
+
+ interface
+
+ ! Boolean module function
+ module logical &
+ function child_function_obf() result(child_stuff)
+ end function
+
+ ! Module subroutine
+ module subroutine &
+ grandchild_subroutine_obf()
+ end subroutine
+
+ end interface
+
+ contains
+
+ module logical function child_function_obf() result(child_stuff)
+ child_stuff=.true.
+ end function
+
+ module subroutine grandchild_subroutine_obf()
+ print *,"Test passed."
+ end subroutine
+
+end module obfuscated_parent
diff --git a/Tests/FortranModules/test_module_main.f90 b/Tests/FortranModules/test_module_main.f90
index 6ac97fa91..958d0a293 100644
--- a/Tests/FortranModules/test_module_main.f90
+++ b/Tests/FortranModules/test_module_main.f90
@@ -1,4 +1,4 @@
PROGRAM MAINF90
- USE TEST_MODULE
+ USE TEST_MODULE, only : TEST_MODULE_FUNCTION
PRINT *,'Sum is',TEST_MODULE_FUNCTION(1., 2.)
END PROGRAM MAINF90
diff --git a/Tests/FunctionTest/CMakeLists.txt b/Tests/FunctionTest/CMakeLists.txt
index 64504470d..0660d0fa3 100644
--- a/Tests/FunctionTest/CMakeLists.txt
+++ b/Tests/FunctionTest/CMakeLists.txt
@@ -51,7 +51,7 @@ track_find_variable(testvar is_changed)
if ("${is_changed}" STREQUAL changed)
pass("same argument name test")
else ()
- pass("same argument name test")
+ fail("same argument name test" "Got: ${is_changed}")
endif ()
include("Util.cmake")
@@ -59,7 +59,7 @@ tester()
if (tester_res STREQUAL "${CMAKE_CURRENT_LIST_FILE}")
pass("CMAKE_CURRENT_LIST_FILE test")
else ()
- pass("CMAKE_CURRENT_LIST_FILE test")
+ fail("CMAKE_CURRENT_LIST_FILE test" "Got: ${tester_res}")
endif ()
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index bb4b92c1b..e82cea2fe 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -121,12 +121,66 @@ add_library(ordertest ordertest.cpp)
target_include_directories(ordertest SYSTEM PUBLIC SystemIncludeDirectories/systemlib)
target_include_directories(ordertest PUBLIC SystemIncludeDirectories/userlib)
+# Test "IMPORTED_NO_SYSTEM" property and its interaction with "SYSTEM"
add_library(ordertest2 ordertest.cpp)
target_include_directories(ordertest2 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
target_link_libraries(ordertest2 PRIVATE ordertest2_userlib)
add_library(ordertest2_userlib INTERFACE IMPORTED)
target_include_directories(ordertest2_userlib INTERFACE SystemIncludeDirectories/userlib)
set_property(TARGET ordertest2_userlib PROPERTY IMPORTED_NO_SYSTEM 1)
+get_property(system_prop_value TARGET ordertest2_userlib PROPERTY SYSTEM)
+if (NOT system_prop_value)
+ message(SEND_ERROR "ordertest2_userlib SYSTEM property should be ON.")
+endif()
+
+# Test "SYSTEM" property of non-imported libraries
+add_library(ordertest3_systemlib INTERFACE)
+target_include_directories(ordertest3_systemlib INTERFACE SystemIncludeDirectories/systemlib)
+set_property(TARGET ordertest3_systemlib PROPERTY SYSTEM 1)
+add_library(ordertest3_userlib INTERFACE)
+target_include_directories(ordertest3_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest3 ordertest.cpp)
+target_link_libraries(ordertest3 PRIVATE ordertest3_systemlib ordertest3_userlib)
+
+# Test "SYSTEM" property of imported libraries and its interaction with "IMPORTED_NO_SYSTEM"
+add_library(ordertest4 ordertest.cpp)
+target_include_directories(ordertest4 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
+target_link_libraries(ordertest4 PRIVATE ordertest4_userlib)
+add_library(ordertest4_userlib INTERFACE IMPORTED)
+target_include_directories(ordertest4_userlib INTERFACE SystemIncludeDirectories/userlib)
+set_property(TARGET ordertest4_userlib PROPERTY SYSTEM 0)
+get_property(imported_no_system_prop_value TARGET ordertest4_userlib PROPERTY IMPORTED_NO_SYSTEM)
+if (imported_no_system_prop_value)
+ message(SEND_ERROR "ordertest4_userlib IMPORTED_NO_SYSTEM property should be OFF.")
+endif()
+
+# Test the interaction between "SYSTEM" and "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"
+add_library(ordertest5_systemlib INTERFACE)
+target_include_directories(ordertest5_systemlib SYSTEM INTERFACE SystemIncludeDirectories/systemlib)
+# The default value of `SYSTEM` is already `OFF`. Here we explicitly set it again.
+set_property(TARGET ordertest5_systemlib PROPERTY SYSTEM 0)
+add_library(ordertest5_userlib INTERFACE)
+target_include_directories(ordertest5_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest5 ordertest.cpp)
+target_link_libraries(ordertest5 PRIVATE ordertest5_systemlib ordertest5_userlib)
+
+# Test that the include of imported executable is treated as system by default.
+add_executable(ordertest6_systemexe IMPORTED)
+target_include_directories(ordertest6_systemexe INTERFACE SystemIncludeDirectories/systemlib)
+set_property(TARGET ordertest6_systemexe PROPERTY ENABLE_EXPORTS 1)
+add_library(ordertest6_userlib INTERFACE)
+target_include_directories(ordertest6_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest6 ordertest.cpp)
+target_link_libraries(ordertest6 PRIVATE ordertest6_systemexe ordertest6_userlib)
+
+# Test that the include of imported executable is not treated as system if "SYSTEM" property is OFF.
+add_library(ordertest7 ordertest.cpp)
+target_include_directories(ordertest7 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
+target_link_libraries(ordertest7 PRIVATE ordertest7_userexe)
+add_library(ordertest7_userexe INTERFACE IMPORTED)
+target_include_directories(ordertest7_userexe INTERFACE SystemIncludeDirectories/userlib)
+set_property(TARGET ordertest7_userexe PROPERTY ENABLE_EXPORTS 1)
+set_property(TARGET ordertest7_userexe PROPERTY SYSTEM 0)
add_subdirectory(StandardIncludeDirectories)
add_subdirectory(TargetIncludeDirectories)
diff --git a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
index af7b09259..7176ebe9d 100644
--- a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
+++ b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
@@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf));
- sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d",
- info->CAPI->GetCacheMajorVersion(mf),
- info->CAPI->GetCacheMinorVersion(mf),
- info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
+ snprintf(
+ buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d",
+ info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf),
+ info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
info->CAPI->DisplaySatus(mf, buffer);
if (info->CAPI->CommandExists(mf, "SET")) {
info->CAPI->DisplaySatus(mf, "Command SET exists");
@@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
source_file = info->CAPI->CreateNewSourceFile(mf);
cstr = info->CAPI->SourceFileGetSourceName(source_file);
- sprintf(buffer, "Should be empty (source file name): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]",
+ cstr);
info->CAPI->DisplaySatus(mf, buffer);
cstr = info->CAPI->SourceFileGetFullPath(source_file);
- sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be empty (source file full path): [%s]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop",
"This property is no longer used", 0);
@@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
"This property is for testing.", 0);
info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
- sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be 0 (source file abstract property): [%p]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DestroySourceFile(source_file);
diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
index af7b09259..7176ebe9d 100644
--- a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
+++ b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
@@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf));
- sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d",
- info->CAPI->GetCacheMajorVersion(mf),
- info->CAPI->GetCacheMinorVersion(mf),
- info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
+ snprintf(
+ buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d",
+ info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf),
+ info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
info->CAPI->DisplaySatus(mf, buffer);
if (info->CAPI->CommandExists(mf, "SET")) {
info->CAPI->DisplaySatus(mf, "Command SET exists");
@@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
source_file = info->CAPI->CreateNewSourceFile(mf);
cstr = info->CAPI->SourceFileGetSourceName(source_file);
- sprintf(buffer, "Should be empty (source file name): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]",
+ cstr);
info->CAPI->DisplaySatus(mf, buffer);
cstr = info->CAPI->SourceFileGetFullPath(source_file);
- sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be empty (source file full path): [%s]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop",
"This property is no longer used", 0);
@@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
"This property is for testing.", 0);
info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
- sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be 0 (source file abstract property): [%p]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DestroySourceFile(source_file);
diff --git a/Tests/MSVCDebugInformationFormat/CMakeLists.txt b/Tests/MSVCDebugInformationFormat/CMakeLists.txt
new file mode 100644
index 000000000..b09bc6c41
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/CMakeLists.txt
@@ -0,0 +1,81 @@
+cmake_minimum_required(VERSION 3.24)
+cmake_policy(SET CMP0141 NEW)
+
+# The debug information format flags do not change preprocessor definitions,
+# so override our table of flags to artificially add a definition we can check.
+set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/override-C.cmake)
+set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/override-CXX.cmake)
+set(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA ${CMAKE_CURRENT_SOURCE_DIR}/override-CUDA.cmake)
+set(CMAKE_USER_MAKE_RULES_OVERRIDE_Fortran ${CMAKE_CURRENT_SOURCE_DIR}/override-Fortran.cmake)
+
+project(MSVCDebugInformationFormat)
+if(CMake_TEST_CUDA)
+ enable_language(CUDA)
+endif()
+if(CMake_TEST_Fortran)
+ enable_language(Fortran)
+endif()
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+if("${CMAKE_C_COMPILER_ID};${CMAKE_C_SIMULATE_ID};${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang;MSVC;GNU")
+ set(verify_default VERIFY_Z7)
+ set(NO_COMPILER_PDB 1)
+elseif("${CMAKE_C_COMPILER_ID};${CMAKE_C_SIMULATE_ID};${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang;MSVC;MSVC")
+ set(verify_default VERIFY_Zi)
+ set(NO_EDIT_AND_CONTINUE 1)
+else()
+ set(verify_default VERIFY_Zi)
+endif()
+
+set(verify_def_Embedded -DVERIFY_Z7)
+set(verify_def_ProgramDatabase -DVERIFY_Zi)
+set(verify_def_EditAndContinue -DVERIFY_ZI)
+
+function(verify_combination format lang src)
+ # Test that try_compile builds with this debug format.
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "${format}")
+ set(CMAKE_TRY_COMPILE_CONFIGURATION "Debug")
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+ try_compile(${format}_COMPILES
+ ${CMAKE_CURRENT_BINARY_DIR}/try_compile/${format}
+ ${CMAKE_CURRENT_SOURCE_DIR}/${src}
+ COMPILE_DEFINITIONS ${verify_def_${format}}
+ CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}
+ OUTPUT_VARIABLE ${format}_OUTPUT
+ )
+ if(${format}_COMPILES)
+ message(STATUS "try_compile ${lang} with ${format} worked")
+ else()
+ string(REPLACE "\n" "\n " ${format}_OUTPUT " ${${format}_OUTPUT}")
+ message(SEND_ERROR "try_compile ${lang} with ${format} failed:\n${${format}_OUTPUT}")
+ endif()
+
+ # Test that targets build with this debug format.
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${format}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>")
+ add_library(${format}-${lang} ${src})
+ set_property(TARGET ${format}-${lang} PROPERTY BOOL_TRUE TRUE)
+ target_compile_definitions(${format}-${lang} PRIVATE ${verify_def_${format}})
+endfunction()
+
+function(verify lang src)
+ add_library(default-${lang} ${src})
+ target_compile_definitions(default-${lang} PRIVATE "$<$<CONFIG:Debug,RelWithDebInfo>:${verify_default}>")
+
+ verify_combination(Embedded ${lang} ${src})
+ if(NOT NO_COMPILER_PDB)
+ verify_combination(ProgramDatabase ${lang} ${src})
+ if(NOT NO_EDIT_AND_CONTINUE AND NOT lang MATCHES "^(Fortran)$")
+ verify_combination(EditAndContinue ${lang} ${src})
+ endif()
+ endif()
+endfunction()
+
+verify(C verify.c)
+verify(CXX verify.cxx)
+if(CMake_TEST_CUDA)
+ verify(CUDA verify.cu)
+endif()
+if(CMake_TEST_Fortran)
+ verify(Fortran verify.F90)
+endif()
diff --git a/Tests/MSVCDebugInformationFormat/override-C.cmake b/Tests/MSVCDebugInformationFormat/override-C.cmake
new file mode 100644
index 000000000..e8f5ae41e
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/override-C.cmake
@@ -0,0 +1,7 @@
+set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
+string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}")
+string(REPLACE "-gcodeview" "-gcodeview;-DTEST_Z7" "${var}" "${${var}}")
+set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase")
+string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}")
+set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue")
+string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}")
diff --git a/Tests/MSVCDebugInformationFormat/override-CUDA.cmake b/Tests/MSVCDebugInformationFormat/override-CUDA.cmake
new file mode 100644
index 000000000..f870775f5
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/override-CUDA.cmake
@@ -0,0 +1,6 @@
+set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
+string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}")
+set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase")
+string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}")
+set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue")
+string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}")
diff --git a/Tests/MSVCDebugInformationFormat/override-CXX.cmake b/Tests/MSVCDebugInformationFormat/override-CXX.cmake
new file mode 100644
index 000000000..caa23fe47
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/override-CXX.cmake
@@ -0,0 +1,7 @@
+set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
+string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}")
+string(REPLACE "-gcodeview" "-gcodeview;-DTEST_Z7" "${var}" "${${var}}")
+set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase")
+string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}")
+set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue")
+string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}")
diff --git a/Tests/MSVCDebugInformationFormat/override-Fortran.cmake b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake
new file mode 100644
index 000000000..5d2db58af
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake
@@ -0,0 +1,4 @@
+set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
+string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}")
+set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase")
+string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}")
diff --git a/Tests/MSVCDebugInformationFormat/verify.F90 b/Tests/MSVCDebugInformationFormat/verify.F90
new file mode 100644
index 000000000..741bca6b8
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/verify.F90
@@ -0,0 +1 @@
+#include "verify.h"
diff --git a/Tests/MSVCDebugInformationFormat/verify.c b/Tests/MSVCDebugInformationFormat/verify.c
new file mode 100644
index 000000000..741bca6b8
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/verify.c
@@ -0,0 +1 @@
+#include "verify.h"
diff --git a/Tests/MSVCDebugInformationFormat/verify.cu b/Tests/MSVCDebugInformationFormat/verify.cu
new file mode 100644
index 000000000..741bca6b8
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/verify.cu
@@ -0,0 +1 @@
+#include "verify.h"
diff --git a/Tests/MSVCDebugInformationFormat/verify.cxx b/Tests/MSVCDebugInformationFormat/verify.cxx
new file mode 100644
index 000000000..741bca6b8
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/verify.cxx
@@ -0,0 +1 @@
+#include "verify.h"
diff --git a/Tests/MSVCDebugInformationFormat/verify.h b/Tests/MSVCDebugInformationFormat/verify.h
new file mode 100644
index 000000000..4bd6529ea
--- /dev/null
+++ b/Tests/MSVCDebugInformationFormat/verify.h
@@ -0,0 +1,29 @@
+#ifdef VERIFY_Z7
+# ifndef TEST_Z7
+# error "TEST_Z7 incorrectly not defined by debug format selection"
+# endif
+#else
+# ifdef TEST_Z7
+# error "TEST_Z7 incorrectly defined by non-debug format selection"
+# endif
+#endif
+
+#ifdef VERIFY_Zi
+# ifndef TEST_Zi
+# error "TEST_Zi incorrectly not defined by debug format selection"
+# endif
+#else
+# ifdef TEST_Zi
+# error "TEST_Zi incorrectly defined by non-debug format selection"
+# endif
+#endif
+
+#ifdef VERIFY_ZI
+# ifndef TEST_ZI
+# error "TEST_ZI incorrectly not defined by debug format selection"
+# endif
+#else
+# ifdef TEST_ZI
+# error "TEST_ZI incorrectly defined by non-debug format selection"
+# endif
+#endif
diff --git a/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt b/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt
new file mode 100644
index 000000000..9dd670e5a
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.8)
+project(CheckIPOSupported-CUDA LANGUAGES CUDA)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT ipo_supported OUTPUT ipo_output)
+if(ipo_supported)
+ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
+endif()
+
+if(NOT ipo_supported AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA"
+ AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2)
+ message(FATAL_ERROR "CheckIPOSupported failed to correctly identify NVIDIA CUDA IPO support")
+endif()
+
+set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
+
+add_library(foo STATIC foo.cu)
+set_target_properties(foo PROPERTIES
+ WINDOWS_EXPORT_ALL_SYMBOLS ON
+ POSITION_INDEPENDENT_CODE ON)
+
+add_library(bar SHARED bar.cu)
+set_target_properties(bar PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
+target_link_libraries(bar PRIVATE foo)
+
+add_executable(CheckIPOSupported-CUDA main.cu)
+target_link_libraries(CheckIPOSupported-CUDA PUBLIC bar)
+
+enable_testing()
+add_test(NAME CheckIPOSupported-CUDA COMMAND CheckIPOSupported-CUDA)
diff --git a/Tests/Module/CheckIPOSupported-CUDA/bar.cu b/Tests/Module/CheckIPOSupported-CUDA/bar.cu
new file mode 100644
index 000000000..79b276db2
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CUDA/bar.cu
@@ -0,0 +1,12 @@
+__device__ int foo_func(int);
+
+void __global__ bar_kernel(int x)
+{
+ foo_func(x);
+}
+
+int launch_kernel(int x)
+{
+ bar_kernel<<<1, 1>>>(x);
+ return x;
+}
diff --git a/Tests/Module/CheckIPOSupported-CUDA/foo.cu b/Tests/Module/CheckIPOSupported-CUDA/foo.cu
new file mode 100644
index 000000000..416607bdd
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CUDA/foo.cu
@@ -0,0 +1,4 @@
+extern __device__ int foo_func(int a)
+{
+ return a * 42 + 9;
+}
diff --git a/Tests/Module/CheckIPOSupported-CUDA/main.cu b/Tests/Module/CheckIPOSupported-CUDA/main.cu
new file mode 100644
index 000000000..8ef487338
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CUDA/main.cu
@@ -0,0 +1,62 @@
+#include <iostream>
+
+#include "cuda.h"
+
+#ifdef _WIN32
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+IMPORT int launch_kernel(int x);
+
+int choose_cuda_device()
+{
+ int nDevices = 0;
+ cudaError_t err = cudaGetDeviceCount(&nDevices);
+ if (err != cudaSuccess) {
+ std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+ << std::endl;
+ return 1;
+ }
+ for (int i = 0; i < nDevices; ++i) {
+ cudaDeviceProp prop;
+ cudaError_t err = cudaGetDeviceProperties(&prop, i);
+ if (err != cudaSuccess) {
+ std::cerr << "Could not retrieve properties from CUDA device " << i
+ << std::endl;
+ return 1;
+ }
+ std::cout << "prop.major: " << prop.major << std::endl;
+ err = cudaSetDevice(i);
+ if (err != cudaSuccess) {
+ std::cout << "Could not select CUDA device " << i << std::endl;
+ } else {
+ return 0;
+ }
+ }
+
+ std::cout << "Could not find a CUDA enabled card" << std::endl;
+
+ return 1;
+}
+
+int main()
+{
+ int ret = choose_cuda_device();
+ if (ret) {
+ return 0;
+ }
+
+ cudaError_t err;
+ launch_kernel(1);
+ err = cudaGetLastError();
+ if (err != cudaSuccess) {
+ std::cerr << "launch_kernel: kernel launch should have passed.\n "
+ "Error message: "
+ << cudaGetErrorString(err) << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index 567fb4b9f..483bd8b21 100644
--- a/Tests/ModuleDefinition/CMakeLists.txt
+++ b/Tests/ModuleDefinition/CMakeLists.txt
@@ -15,7 +15,17 @@ add_custom_command(OUTPUT example_dll_gen.def
add_library(example_dll_gen SHARED example_dll_gen.c example_dll_gen.def)
# Test /DEF:<file> flag recognition for VS.
-if(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
+if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
+ # IntelLLVM for MSVC frontend variant needs the /DEF flag wrapped to be sent
+ # to the linker, which happens automatically when the DEF file is added
+ # to the sources.
+ add_library(example_dll_2 SHARED
+ example_dll_2.c
+ "${ModuleDefinition_SOURCE_DIR}/example_dll_2.def"
+ )
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS EXAMPLE_DLL_2)
+ set(example_dll_2 example_dll_2)
+elseif(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
add_library(example_dll_2 SHARED example_dll_2.c)
set_property(TARGET example_dll_2 PROPERTY LINK_FLAGS
/DEF:"${ModuleDefinition_SOURCE_DIR}/example_dll_2.def")
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt
index 4347459f1..84ca5e8a9 100644
--- a/Tests/Preprocess/CMakeLists.txt
+++ b/Tests/Preprocess/CMakeLists.txt
@@ -197,9 +197,14 @@ endif()
#-----------------------------------------------------------------------------
# Inform the test if the debug configuration is getting built.
-# The NDEBUG definition takes care of this for release.
string(APPEND CMAKE_C_FLAGS_DEBUG " -DPREPROCESS_DEBUG")
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -DPREPROCESS_DEBUG")
+string(APPEND CMAKE_C_FLAGS_RELEASE " -DPREPROCESS_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DPREPROCESS_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG")
+string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG")
# Inform the test if it built from Xcode.
if(PP_XCODE)
diff --git a/Tests/Preprocess/preprocess.c b/Tests/Preprocess/preprocess.c
index b3117da5f..88f9e97e0 100644
--- a/Tests/Preprocess/preprocess.c
+++ b/Tests/Preprocess/preprocess.c
@@ -33,7 +33,7 @@ int check_defines_C(void)
result = 0;
}
}
-#ifdef NDEBUG
+#ifdef PREPROCESS_NDEBUG
# ifdef FILE_DEF_DEBUG
{
fprintf(stderr, "FILE_DEF_DEBUG should not be defined in C\n");
diff --git a/Tests/Preprocess/preprocess.cxx b/Tests/Preprocess/preprocess.cxx
index f2fffef72..50150d1cc 100644
--- a/Tests/Preprocess/preprocess.cxx
+++ b/Tests/Preprocess/preprocess.cxx
@@ -35,7 +35,7 @@ int check_defines_CXX()
result = 0;
}
}
-#ifdef NDEBUG
+#ifdef PREPROCESS_NDEBUG
# ifdef FILE_DEF_DEBUG
{
fprintf(stderr, "FILE_DEF_DEBUG should not be defined in CXX\n");
diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
index dbcf4b8a5..fe57d5661 100644
--- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake
+++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
@@ -7,7 +7,7 @@ set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
add_library(autoexport SHARED hello.cxx world.cxx foo.c $<TARGET_OBJECTS:objlib>)
add_library(autoexport3 SHARED cppCLI.cxx)
if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600
- AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
set_property(TARGET autoexport3 PROPERTY COMMON_LANGUAGE_RUNTIME "")
endif()
@@ -17,7 +17,7 @@ if(MSVC)
add_library(autoexport_for_exec SHARED hello2.c)
target_link_libraries(autoexport_for_exec say)
if(NOT MSVC_VERSION VERSION_LESS 1600 AND
- NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
enable_language(ASM_MASM)
target_sources(autoexport PRIVATE nop.asm)
set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh)
diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
index 06f416b8c..809907931 100644
--- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
+++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
@@ -60,8 +60,7 @@ set(run_BuildDepends_skip_step_3 1)
run_BuildDepends(C-Exe)
if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
- if(RunCMake_GENERATOR MATCHES "Visual Studio 10" OR
- RunCMake_GENERATOR_TOOLSET MATCHES "^(v80|v90|v100)$")
+ if(RunCMake_GENERATOR_TOOLSET MATCHES "^(v80|v90|v100)$")
# VS 10 forgets to re-link when a manifest changes
set(run_BuildDepends_skip_step_2 1)
endif()
diff --git a/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt
new file mode 100644
index 000000000..5d09fcf58
--- /dev/null
+++ b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0102-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0102 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
index 61e046f89..074db6556 100644
--- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
@@ -4,3 +4,4 @@ run_cmake_script(Regex-CMP0127-NEW)
run_cmake_script(Regex-CMP0127-OLD)
run_cmake_script(Parentheses-CMP0127-NEW)
run_cmake_script(Parentheses-CMP0127-WARN)
+run_cmake_script(UseDotSymbol)
diff --git a/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt
new file mode 100644
index 000000000..15b56a10d
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt
@@ -0,0 +1 @@
+-- USE_FOO='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake
new file mode 100644
index 000000000..8f07c4814
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake
@@ -0,0 +1,4 @@
+include(CMakeDependentOption)
+
+cmake_dependent_option(USE_FOO "Use Foo" ON "CMAKE_VERSION VERSION_GREATER_EQUAL 3.08" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 09f248e55..3038ed846 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -197,6 +197,10 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
${ninja_qt_args}
)
endif()
+ if(WIN32)
+ add_executable(showIncludes showIncludes.c)
+ list(APPEND Ninja_ARGS -DshowIncludes=$<TARGET_FILE:showIncludes>)
+ endif()
add_RunCMake_test(Ninja)
set(NinjaMultiConfig_ARGS
-DCYGWIN=${CYGWIN} -DMSYS=${MSYS}
@@ -295,6 +299,19 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(CompilerChange)
endif()
add_RunCMake_test(CompilerNotFound)
+if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
+ list(APPEND CompilerTest_ARGS -DCMake_TEST_OBJC=1)
+endif()
+if(CMAKE_Fortran_COMPILER)
+ list(APPEND CompilerTest_ARGS -DCMake_TEST_Fortran=1)
+endif()
+foreach(lang IN ITEMS CUDA HIP ISPC)
+ if(CMake_TEST_${lang})
+ list(APPEND CompilerTest_ARGS -DCMake_TEST_${lang}=1)
+ endif()
+endforeach()
+add_RunCMake_test(CompilerTest)
+set_property(TEST RunCMake.CompilerTest APPEND PROPERTY LABELS "CUDA" "HIP" "ISPC")
add_RunCMake_test(Configure -DMSVC_IDE=${MSVC_IDE})
add_RunCMake_test(DisallowedCommands)
if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
@@ -305,6 +322,9 @@ add_RunCMake_test(ExportImport)
add_RunCMake_test(ExternalData)
add_RunCMake_test(FeatureSummary)
add_RunCMake_test(FPHSA)
+if(CMAKE_USE_SYSTEM_JSONCPP)
+ list(APPEND FileAPI_ARGS -DJsonCpp_VERSION_STRING=${JsonCpp_VERSION_STRING})
+endif()
add_RunCMake_test(FileAPI -DPython_EXECUTABLE=${Python_EXECUTABLE}
-DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID})
add_RunCMake_test(FindBoost)
@@ -356,6 +376,7 @@ if(MSVC)
add_RunCMake_test(MSVCRuntimeLibrary)
add_RunCMake_test(MSVCRuntimeTypeInfo)
add_RunCMake_test(MSVCWarningFlags)
+ add_RunCMake_test(MSVCDebugInformationFormat)
endif()
if(XCODE_VERSION)
set(ObjectLibrary_ARGS -DXCODE_VERSION=${XCODE_VERSION})
@@ -453,6 +474,7 @@ add_RunCMake_test(find_path)
add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(foreach)
add_RunCMake_test(function)
+add_RunCMake_test(block)
add_RunCMake_test(get_filename_component)
add_RunCMake_test(get_property)
add_RunCMake_test(if)
@@ -522,7 +544,9 @@ function(add_RunCMake_test_try_compile)
set(CMAKE_CXX_STANDARD_DEFAULT 14)
endif()
endif()
- foreach(var
+ foreach(
+ var
+ IN ITEMS
CMAKE_SYSTEM_NAME
CMAKE_C_COMPILER_ID
CMAKE_C_COMPILER_VERSION
@@ -536,7 +560,7 @@ function(add_RunCMake_test_try_compile)
CMake_TEST_FILESYSTEM_1S
CMAKE_OBJC_STANDARD_DEFAULT
CMAKE_OBJCXX_STANDARD_DEFAULT
- )
+ )
if(DEFINED ${var})
list(APPEND try_compile_ARGS -D${var}=${${var}})
endif()
@@ -566,6 +590,9 @@ if(CMake_TEST_CUDA)
endif()
add_RunCMake_test(DependencyGraph -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER})
+# Add C++ Module tests.
+add_RunCMake_test(CXXModules -DCMake_TEST_MODULE_COMPILATION=${CMake_TEST_MODULE_COMPILATION} -DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES})
+
# ctresalloc links against CMakeLib and CTestLib, which means it can't be built
# if CMake_TEST_EXTERNAL_CMAKE is activated (the compiler might be different.)
# So, it has to be provided in the original build tree.
@@ -689,6 +716,8 @@ add_RunCMake_test(target_link_libraries-LINK_LIBRARY -DCMAKE_SYSTEM_NAME=${CMAKE
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}
-DMSVC_VERSION=${MSVC_VERSION}
+ -DXCODE=${XCODE}
+ -DXCODE_VERSION=${XCODE_VERSION}
-DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
-DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}
-DCMAKE_IMPORT_LIBRARY_PREFIX=${CMAKE_IMPORT_LIBRARY_PREFIX}
@@ -948,7 +977,7 @@ if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN)
if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja|Visual Studio 1[456]")
message(FATAL_ERROR "Android tests supported only by Makefile, Ninja, and Visual Studio >= 14 generators")
endif()
- foreach(v TEST_ANDROID_NDK TEST_ANDROID_STANDALONE_TOOLCHAIN)
+ foreach(v IN ITEMS TEST_ANDROID_NDK TEST_ANDROID_STANDALONE_TOOLCHAIN)
if(CMake_${v})
string(REPLACE ";" "|" ${v} "${CMake_${v}}")
list(APPEND Android_ARGS "-D${v}=${${v}}")
@@ -967,7 +996,7 @@ endif()
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
add_RunCMake_test(CSharpCustomCommand)
- if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
add_RunCMake_test(CSharpReferenceImport)
endif()
endif()
@@ -992,6 +1021,14 @@ add_RunCMake_test(CMakePresetsTest
-DPython_EXECUTABLE=${Python_EXECUTABLE}
-DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}
)
+add_RunCMake_test(CMakePresetsPackage
+ -DPython_EXECUTABLE=${Python_EXECUTABLE}
+ -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}
+ )
+add_RunCMake_test(CMakePresetsWorkflow
+ -DPython_EXECUTABLE=${Python_EXECUTABLE}
+ -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}
+ )
add_RunCMake_test(VerifyHeaderSets)
diff --git a/Tests/RunCMake/CMakePresets/Comment-stderr.txt b/Tests/RunCMake/CMakePresets/Comment-stderr.txt
index 2f404bc45..b3b6b66d9 100644
--- a/Tests/RunCMake/CMakePresets/Comment-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/Comment-stderr.txt
@@ -1,2 +1,9 @@
^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/Comment: JSON parse error$
+]*/Tests/RunCMake/CMakePresets/Comment: JSON parse error
+Errors:
+[^
+]*Comment\/CMakePresets.json:
+\* Line 1, Column 1
+ Syntax error: value, object or array expected\.
+\* Line 2, Column 1
+ Extra non-whitespace after JSON value\.$
diff --git a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt
new file mode 100644
index 000000000..57b714d74
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt
@@ -0,0 +1,22 @@
+^Not searching for unused variables given on the command line\.
+Available configure presets:
+
+ "default" ?- Default Config
+ "ninja-multi" ?- Ninja Multi-Config(
+ "windows-only" - Windows-only configuration)?
+
+Available build presets:
+
+ "default"
+
+Available test presets:
+
+ "default"
+
+Available package presets:
+
+ "default"
+
+Available workflow presets:
+
+ "default"$
diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
index 6970674c7..0d3c5001a 100644
--- a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset$
+]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset
+Errors:
+[^
+]*/EmptyPresetName/CMakePresets.json$
diff --git a/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake b/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake
index df58e72e4..d9e399fbb 100644
--- a/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake
+++ b/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake
@@ -1,4 +1,5 @@
include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+file(REAL_PATH "${_parent}" _parent)
test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodNoSCachePrep-build")
diff --git a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt
index 7ccabab0f..85a2d7890 100644
--- a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/IncludeNotFound: File not found$
+]*/Tests/RunCMake/CMakePresets/IncludeNotFound: File not found
+Errors:
+[^
+]*/IncludeNotFound/NotFound.json: Failed to read file$
diff --git a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt
index a43bf77be..89eff9fc5 100644
--- a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt
@@ -1,2 +1,9 @@
^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error$
+]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error
+Errors:
+[^
+]*JSONParseError/CMakePresets.json:
+\* Line 1, Column 1
+ Syntax error: value, object or array expected\.
+\* Line 1, Column 1
+ A valid JSON document must be either an array or an object value\.$
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt
new file mode 100644
index 000000000..38f52aa5b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt
@@ -0,0 +1,8 @@
+^Not searching for unused variables given on the command line.
+Available configure presets:
+
+ "default"
+
+Available test presets:
+
+ "default"$
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in
new file mode 100644
index 000000000..92594777b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt
new file mode 100644
index 000000000..8cac0a88a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt
@@ -0,0 +1,8 @@
+^Not searching for unused variables given on the command line.
+Available configure presets:
+
+ "default"
+
+Available build presets:
+
+ "default"$
diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in
new file mode 100644
index 000000000..33fd0362a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt
new file mode 100644
index 000000000..153abeea2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Invalid value specified for --list-presets\.
+Valid values are configure, build, test, package, or all\. When no value is passed the default is configure\.
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index d097086db..efa838e82 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -289,6 +289,7 @@ run_cmake_presets(UserInheritance)
# Test listing presets
set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListPresets.json.in")
run_cmake_presets(ListPresets --list-presets)
+run_cmake_presets(ListPresetsInvalidType --list-presets=invalid-type)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ListPresetsWorkingDir")
set(RunCMake_TEST_NO_CLEAN 1)
@@ -304,6 +305,12 @@ unset(RunCMake_TEST_BINARY_DIR)
run_cmake_presets(ListPresetsNoSuchPreset)
run_cmake_presets(ListPresetsHidden)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListAllPresetsNoBuild.json.in")
+run_cmake_presets(ListAllPresetsNoBuild --list-presets=all)
+
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListAllPresetsNoTest.json.in")
+run_cmake_presets(ListAllPresetsNoTest --list-presets=all)
+
# Test warning and error flags
set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings.json.in")
set(CMakePresets_WARN_UNUSED_CLI 1)
@@ -401,4 +408,5 @@ set(CMakePresets_EXTRA_FILES
"${RunCMake_SOURCE_DIR}/moreThings.json.in"
)
run_cmake_presets(DocumentationExample --preset=default)
+run_cmake_presets(DocumentationExampleListAllPresets --list-presets=all)
unset(CMakePresets_EXTRA_FILES)
diff --git a/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in
new file mode 100644
index 000000000..129184a89
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project("@CASE_NAME@" NONE)
+include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake
new file mode 100644
index 000000000..40240f97d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake
@@ -0,0 +1,6 @@
+include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+set(filename "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/config-file-alt.tar.gz")
+if(NOT EXISTS "${filename}")
+ set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake
new file mode 100644
index 000000000..3d684af87
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake
@@ -0,0 +1,18 @@
+if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+ set(cpack_dir "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}")
+ set(contents [[Debug
+Release
+]])
+
+ file(GLOB dirs RELATIVE "${cpack_dir}" "${cpack_dir}/*")
+ foreach(dir IN LISTS dirs)
+ set(configs_file "${cpack_dir}/${dir}/${CPACK_PACKAGE_FILE_NAME}/configs.txt")
+ file(READ "${configs_file}" actual_contents)
+ if(NOT contents STREQUAL actual_contents)
+ string(REPLACE "\n" "\n " contents_formatted "${contents}")
+ string(REPLACE "\n" "\n " actual_contents_formatted "${actual_contents}")
+ string(APPEND RunCMake_TEST_FAILED "Expected contents of ${configs_file}:\n ${contents_formatted}\nActual contents:\n ${actual_contents_formatted}\n")
+ endif()
+ endforeach()
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt
new file mode 100644
index 000000000..be885b4cc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt
@@ -0,0 +1,2 @@
+CPack: [^
+]* Enable Debug
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake
new file mode 100644
index 000000000..aaa75e469
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake
@@ -0,0 +1 @@
+check_cpack_packages("TBZ2;TXZ" "")
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake
new file mode 100644
index 000000000..205e7b7d4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake
@@ -0,0 +1,7 @@
+check_cpack_packages("TGZ;TXZ" [[TEST_ENV not defined
+TEST_ENV_REF=xx
+TEST_ENV_OVERRIDE not defined
+TEST_ENV_OVERRIDE_REF not defined
+]])
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake
new file mode 100644
index 000000000..8f4b771c5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake
@@ -0,0 +1,6 @@
+include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+set(filename "${RunCMake_TEST_BINARY_DIR}/default/package-directory/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/${CPACK_PACKAGE_FILE_NAME}.tar.gz")
+if(NOT EXISTS "${filename}")
+ set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake
new file mode 100644
index 000000000..fdc482496
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake
@@ -0,0 +1,7 @@
+include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/default/${CPACK_PACKAGE_FILE_NAME}.json" contents)
+string(JSON package_name GET "${contents}" packageName)
+if(NOT package_name STREQUAL "package-name")
+ set(RunCMake_TEST_FAILED "Expected package name to be \"package-name\" but it was \"${package_name}\"")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake
new file mode 100644
index 000000000..dba911093
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake
@@ -0,0 +1,7 @@
+include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/default/${CPACK_PACKAGE_FILE_NAME}.json" contents)
+string(JSON package_version GET "${contents}" packageVersion)
+if(NOT package_version STREQUAL "1.0")
+ set(RunCMake_TEST_FAILED "Expected package version to be \"1.0\" but it was \"${package_version}\"")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake
new file mode 100644
index 000000000..2858170fb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake
@@ -0,0 +1,6 @@
+include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+set(filename "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/variables-package.tar.gz")
+if(NOT EXISTS "${filename}")
+ set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt
new file mode 100644
index 000000000..22fd115a1
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt
@@ -0,0 +1 @@
+CPack: Enable Verbose
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake
new file mode 100644
index 000000000..a775e4d30
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake
@@ -0,0 +1,7 @@
+check_cpack_packages("TGZ;TXZ" [[TEST_ENV=Environment variable
+TEST_ENV_REF=xEnvironment variablex
+TEST_ENV_OVERRIDE=Override
+TEST_ENV_OVERRIDE_REF=xOverridex
+]])
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good.cmake b/Tests/RunCMake/CMakePresetsPackage/Good.cmake
new file mode 100644
index 000000000..d01944354
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good.cmake
@@ -0,0 +1,31 @@
+set(CPACK_PACKAGE_NAME Good)
+set(CPACK_GENERATOR "TGZ;TXZ")
+
+include(CPack)
+
+install(CODE [[
+function(print_env name)
+ if(DEFINED ENV{${name}})
+ file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt "${name}=$ENV{${name}}\n")
+ else()
+ file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt "${name} not defined\n")
+ endif()
+endfunction()
+
+file(REMOVE $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt)
+print_env(TEST_ENV)
+print_env(TEST_ENV_REF)
+print_env(TEST_ENV_OVERRIDE)
+print_env(TEST_ENV_OVERRIDE_REF)
+
+file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/configs.txt "$<CONFIG>\n")
+]])
+
+file(WRITE "${CMAKE_BINARY_DIR}/CPackConfigAlt.cmake" [[include(${CMAKE_CURRENT_LIST_DIR}/CPackConfig.cmake)
+set(CPACK_PACKAGE_FILE_NAME "config-file-alt")
+]])
+
+file(WRITE "${CMAKE_BINARY_DIR}/external_package.cmake" [[if(NOT CPACK_PACKAGE_VENDOR STREQUAL "some-vendor")
+ message(FATAL_ERROR "Expected vendor to be \"some-vendor\" but it was \"${CPACK_PACKAGE_VENDOR}\"")
+endif()
+]])
diff --git a/Tests/RunCMake/CMakePresetsPackage/Good.json.in b/Tests/RunCMake/CMakePresetsPackage/Good.json.in
new file mode 100644
index 000000000..0c0e7d916
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/Good.json.in
@@ -0,0 +1,135 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "environment": {
+ "TEST_ENV": "Environment variable",
+ "TEST_ENV_OVERRIDE": "Overridden environment variable"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "build-default-debug",
+ "configurePreset": "default",
+ "configuration": "Debug"
+ },
+ {
+ "name": "build-default-release",
+ "inherits": "build-default-debug",
+ "configuration": "Release"
+ }
+ ],
+ "packagePresets": [
+ {
+ "name": "minimal",
+ "configurePreset": "default"
+ },
+ {
+ "name": "defaults",
+ "hidden": false,
+ "inherits": [],
+ "vendor": {},
+ "displayName": "",
+ "description": "",
+ "environment": {},
+ "configurePreset": "default",
+ "inheritConfigureEnvironment": true
+ },
+ {
+ "name": "no-environment",
+ "configurePreset": "default",
+ "inheritConfigureEnvironment": false,
+ "environment": {
+ "TEST_ENV_REF": "x$env{TEST_ENV}x"
+ }
+ },
+ {
+ "name": "with-environment",
+ "inherits": "no-environment",
+ "inheritConfigureEnvironment": true,
+ "environment": {
+ "TEST_ENV_OVERRIDE": "Override",
+ "TEST_ENV_OVERRIDE_REF": "x$env{TEST_ENV_OVERRIDE}x",
+ "TEST_ENV_REF": "x$env{TEST_ENV}x"
+ }
+ },
+ {
+ "name": "generators",
+ "inherits": "minimal",
+ "generators": [
+ "TBZ2",
+ "TXZ"
+ ]
+ },
+ {
+ "name": "configurations",
+ "inherits": "minimal",
+ "configurations": [
+ "Debug",
+ "Release"
+ ]
+ },
+ {
+ "name": "variables",
+ "inherits": "minimal",
+ "variables": {
+ "CPACK_PACKAGE_FILE_NAME": "variables-package"
+ }
+ },
+ {
+ "name": "config-file",
+ "inherits": "minimal",
+ "configFile": "CPackConfigAlt.cmake"
+ },
+ {
+ "name": "debug",
+ "inherits": "minimal",
+ "output": {
+ "debug": true
+ }
+ },
+ {
+ "name": "verbose",
+ "inherits": "minimal",
+ "output": {
+ "verbose": true
+ }
+ },
+ {
+ "name": "package-name",
+ "inherits": "minimal",
+ "generators": [
+ "External"
+ ],
+ "packageName": "package-name"
+ },
+ {
+ "name": "package-version",
+ "inherits": "minimal",
+ "generators": [
+ "External"
+ ],
+ "packageVersion": "1.0"
+ },
+ {
+ "name": "package-directory",
+ "inherits": "minimal",
+ "packageDirectory": "${sourceDir}/build/default/package-directory"
+ },
+ {
+ "name": "vendor-name",
+ "inherits": "minimal",
+ "generators": [
+ "External"
+ ],
+ "variables": {
+ "CPACK_EXTERNAL_PACKAGE_SCRIPT": "${sourceDir}/build/default/external_package.cmake"
+ },
+ "vendorName": "some-vendor"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt
new file mode 100644
index 000000000..307ec0ae4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt
@@ -0,0 +1,4 @@
+^Available package presets:
+
+ "default"
+ "with-description" - With Description$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake b/Tests/RunCMake/CMakePresetsPackage/ListPresets.cmake
index e69de29bb..e69de29bb 100644
--- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake
+++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets.cmake
diff --git a/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in b/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in
new file mode 100644
index 000000000..5f3cf4868
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in
@@ -0,0 +1,20 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "packagePresets": [
+ {
+ "name": "default",
+ "configurePreset": "default"
+ },
+ {
+ "name": "with-description",
+ "displayName": "With Description",
+ "description": "This preset has a description",
+ "configurePreset": "default"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
new file mode 100644
index 000000000..269fb6e03
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
@@ -0,0 +1,102 @@
+include(RunCMake)
+
+# Presets do not support legacy VS generator name architecture suffix.
+if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ")
+ set(RunCMake_GENERATOR "${CMAKE_MATCH_1}")
+endif()
+
+function(run_cmake_package_presets name CMakePresetsPackage_CONFIGURE_PRESETS CMakePresetsPackage_BUILD_PRESETS CMakePresetsPackage_PACKAGE_PRESETS)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build")
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+
+ set(RunCMake_TEST_NO_CLEAN TRUE)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ set(CASE_NAME "${name}")
+ set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
+
+ if(NOT CMakePresetsPackage_FILE)
+ set(CMakePresetsPackage_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in")
+ endif()
+ if(EXISTS "${CMakePresetsPackage_FILE}")
+ configure_file("${CMakePresetsPackage_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY)
+ endif()
+
+ if(NOT CMakeUserPresets_FILE)
+ set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in")
+ endif()
+ if(EXISTS "${CMakeUserPresets_FILE}")
+ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY)
+ endif()
+
+ foreach(ASSET ${CMakePresetsPackage_ASSETS})
+ configure_file("${RunCMake_SOURCE_DIR}/${ASSET}" "${RunCMake_TEST_SOURCE_DIR}" COPYONLY)
+ endforeach()
+
+ if (NOT CMakePresetsPackage_NO_CONFIGURE)
+ foreach(CONFIGURE_PRESET ${CMakePresetsPackage_CONFIGURE_PRESETS})
+ run_cmake_command("${name}-configure-${CONFIGURE_PRESET}"
+ "${CMAKE_COMMAND}" "--preset" "${CONFIGURE_PRESET}")
+ endforeach()
+ endif()
+
+ if (NOT CMakePresetsPackage_NO_BUILD)
+ foreach(BUILD_PRESET ${CMakePresetsPackage_BUILD_PRESETS})
+ run_cmake_command("${name}-build-${BUILD_PRESET}"
+ "${CMAKE_COMMAND}" "--build" "--preset" "${BUILD_PRESET}")
+ endforeach()
+ endif()
+
+ set(eq 0)
+ foreach(PACKAGE_PRESET ${CMakePresetsPackage_PACKAGE_PRESETS})
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages")
+
+ if (EXISTS "${RunCMake_SOURCE_DIR}/${name}-package-${PACKAGE_PRESET}-check.cmake")
+ set(RunCMake-check-file "${name}-package-${PACKAGE_PRESET}-check.cmake")
+ else()
+ set(RunCMake-check-file "check.cmake")
+ endif()
+
+ if(eq)
+ run_cmake_command(${name}-package-${PACKAGE_PRESET}
+ ${CMAKE_CPACK_COMMAND} "--preset=${PACKAGE_PRESET}" ${ARGN})
+ set(eq 0)
+ else()
+ run_cmake_command(${name}-package-${PACKAGE_PRESET}
+ ${CMAKE_CPACK_COMMAND} "--preset" "${PACKAGE_PRESET}" ${ARGN})
+ set(eq 1)
+ endif()
+ endforeach()
+endfunction()
+
+function(check_cpack_packages generators contents)
+ include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake")
+
+ set(cpack_dir "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}")
+ file(GLOB dirs RELATIVE "${cpack_dir}" "${cpack_dir}/*")
+ if(NOT dirs STREQUAL generators)
+ string(APPEND RunCMake_TEST_FAILED "Expected CPack generators: ${generators}\nActual CPack generators: ${dirs}\n")
+ endif()
+
+ if(contents)
+ foreach(dir IN LISTS dirs)
+ set(env_file "${cpack_dir}/${dir}/${CPACK_PACKAGE_FILE_NAME}/env.txt")
+ file(READ "${env_file}" actual_contents)
+ if(NOT contents STREQUAL actual_contents)
+ string(REPLACE "\n" "\n " contents_formatted "${contents}")
+ string(REPLACE "\n" "\n " actual_contents_formatted "${actual_contents}")
+ string(APPEND RunCMake_TEST_FAILED "Expected contents of ${env_file}:\n ${contents_formatted}\nActual contents:\n ${actual_contents_formatted}\n")
+ endif()
+ endforeach()
+ endif()
+
+ set(RunCMake_TEST_FAILED ${RunCMake_TEST_FAILED} PARENT_SCOPE)
+endfunction()
+
+run_cmake_package_presets(UnsupportedVersion "x" "" "")
+run_cmake_package_presets(Good "default" "build-default-debug" "no-environment;with-environment;generators;configurations;variables;config-file;debug;verbose;package-name;package-version;package-directory;vendor-name")
+run_cmake_package_presets(ListPresets "default" "" "x" "--list-presets")
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt
+++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-result.txt
diff --git a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt
new file mode 100644
index 000000000..4c461e3f8
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion: File version must be 6 or higher for package preset support$
diff --git a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in
new file mode 100644
index 000000000..e5f724070
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 5,
+ "packagePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresetsPackage/check.cmake b/Tests/RunCMake/CMakePresetsPackage/check.cmake
new file mode 100644
index 000000000..e79c4f12a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsPackage/check.cmake
@@ -0,0 +1,3 @@
+set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake b/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake
new file mode 100644
index 000000000..e1788cb83
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake
@@ -0,0 +1,4 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check.cmake")
+if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/default/output.xml")
+ string(APPEND RunCMake_TEST_FAILED "Expected ${RunCMake_TEST_BINARY_DIR}/default/output.xml to exist but it does not\n")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake b/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake
new file mode 100644
index 000000000..e860d4218
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake
@@ -0,0 +1,4 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check.cmake")
+if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/default/output.log")
+ string(APPEND RunCMake_TEST_FAILED "Expected ${RunCMake_TEST_BINARY_DIR}/default/output.log to exist but it does not\n")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsTest/Good.json.in b/Tests/RunCMake/CMakePresetsTest/Good.json.in
index d484a199f..a4b875a1d 100644
--- a/Tests/RunCMake/CMakePresetsTest/Good.json.in
+++ b/Tests/RunCMake/CMakePresetsTest/Good.json.in
@@ -1,5 +1,5 @@
{
- "version": 5,
+ "version": 6,
"configurePresets": [
{
"name": "default",
@@ -171,6 +171,20 @@
"execution": {
"showOnly": "human"
}
+ },
+ {
+ "name": "outputLog",
+ "inherits": "minimal",
+ "output": {
+ "outputLogFile": "${sourceDir}/build/default/output.log"
+ }
+ },
+ {
+ "name": "outputJUnit",
+ "inherits": "minimal",
+ "output": {
+ "outputJUnitFile": "${sourceDir}/build/default/output.xml"
+ }
}
]
}
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt
+++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt
new file mode 100644
index 000000000..acd578548
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported: File version must be 6 or higher for CTest JUnit output support$
diff --git a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in
new file mode 100644
index 000000000..93f6b0c20
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in
@@ -0,0 +1,17 @@
+{
+ "version": 5,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "unsupported",
+ "configurePreset": "default",
+ "output": {
+ "outputJUnitFile": "junit.xml"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
index bec0dd946..1c7b8360f 100644
--- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
@@ -78,7 +78,7 @@ set(CMakePresetsTest_ASSETS "Good-indexFile.txt")
set(GoodTestPresets
"minimal;defaults;noEnvironment;withEnvironment"
"config-debug;config-release"
- "exclude;index;indexFile;showOnly")
+ "exclude;index;indexFile;showOnly;outputLog;outputJUnit")
run_cmake_test_presets(Good
"default"
""
@@ -105,6 +105,8 @@ run_cmake_test_presets(Invalid "" "" "hidden;vendorMacro")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
run_cmake_test_presets(PresetsUnsupported "" "" "x")
run_cmake_test_presets(ConditionFuture "" "" "x")
+run_cmake_test_presets(TestOutputTruncationUnsupported "" "" "x")
+run_cmake_test_presets(OutputJUnitUnsupported "" "" "x")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
run_cmake_test_presets(ConfigurePresetUnreachable "" "" "x")
set(CMakePresetsTest_NO_CONFIGURE 0)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt
+++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt
new file mode 100644
index 000000000..90ea7c3b2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported: File version must be 5 or higher for testOutputTruncation preset support\.$
diff --git a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in
new file mode 100644
index 000000000..c116039af
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in
@@ -0,0 +1,17 @@
+{
+ "version": 4,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "output": {
+ "testOutputTruncation": "tail"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt
new file mode 100644
index 000000000..45a4fb75d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt
new file mode 100644
index 000000000..0690c694b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt
@@ -0,0 +1,4 @@
+^Errors while running CTest
+Output from these tests are in: [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build/Testing/Temporary/LastTest\.log
+Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely\.$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt
new file mode 100644
index 000000000..2f23f8885
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt
@@ -0,0 +1,17 @@
+^Executing workflow step 1 of 4: configure preset "default"
+
+.*Testing the configure step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.*
+
+Executing workflow step 2 of 4: build preset "default"
+
+.*Testing the build step at [^
+]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]BadExitCode[\\/]build.*
+
+Executing workflow step 3 of 4: test preset "default"
+
+.*Testing the test step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.*
+
+The following tests FAILED:
+.* +1 - EchoTest \(Failed\)$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake
new file mode 100644
index 000000000..10b46e3f2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake
@@ -0,0 +1,8 @@
+message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}")
+
+add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}")
+
+enable_testing()
+add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/BadExitCodeTest.cmake")
+
+include(CPack)
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake
new file mode 100644
index 000000000..59f683e60
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR " Testing the test step at ${CMAKE_BINARY_DIR}")
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in
new file mode 100644
index 000000000..129184a89
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project("@CASE_NAME@" NONE)
+include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt
+++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt
new file mode 100644
index 000000000..22ca94d0d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch: Invalid workflow steps$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in
new file mode 100644
index 000000000..086414903
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in
@@ -0,0 +1,32 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "mismatch"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "mismatch",
+ "configurePreset": "mismatch"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ },
+ {
+ "type": "build",
+ "name": "mismatch"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt
index e69de29bb..e69de29bb 100644
--- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake
+++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt
new file mode 100644
index 000000000..cbfee5a5c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure: Invalid workflow steps$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in
new file mode 100644
index 000000000..2c121a8b3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in
@@ -0,0 +1,27 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "binaryDir": "${sourceDir}/build",
+ "generator": "@RunCMake_GENERATOR@"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "build",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Fresh.cmake b/Tests/RunCMake/CMakePresetsWorkflow/Fresh.cmake
new file mode 100644
index 000000000..4cf999f33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/Fresh.cmake
@@ -0,0 +1,4 @@
+option(FRESH_CONFIGURE "" ON)
+if(NOT FRESH_CONFIGURE)
+ message(FATAL_ERROR "FRESH_CONFIGURE is ${FRESH_CONFIGURE}, should be ON")
+endif()
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Fresh.json.in b/Tests/RunCMake/CMakePresetsWorkflow/Fresh.json.in
new file mode 100644
index 000000000..4ce0ca555
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/Fresh.json.in
@@ -0,0 +1,21 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "Fresh",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt
new file mode 100644
index 000000000..a04d7ea14
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt
@@ -0,0 +1,19 @@
+^Executing workflow step 1 of 4: configure preset "default"
+
+.*Testing the configure step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.*
+
+Executing workflow step 2 of 4: build preset "default"
+
+.*Testing the build step at [^
+]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]Good[\\/]build.*
+
+Executing workflow step 3 of 4: test preset "default"
+
+.*Testing the test step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.*
+
+Executing workflow step 4 of 4: package preset "default"
+
+.*Testing the package step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.*
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake
new file mode 100644
index 000000000..31ce7ffb2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake
@@ -0,0 +1,8 @@
+message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}")
+
+add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}")
+
+enable_testing()
+add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -E echo "Testing the test step at ${CMAKE_BINARY_DIR}")
+
+include(CPack)
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in
new file mode 100644
index 000000000..87e29368f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in
@@ -0,0 +1,87 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "binaryDir": "${sourceDir}/build",
+ "generator": "@RunCMake_GENERATOR@"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "configuration": "Debug"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "output": {
+ "verbosity": "verbose"
+ },
+ "configuration": "Debug"
+ }
+ ],
+ "packagePresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "generators": [
+ "External"
+ ],
+ "variables": {
+ "CPACK_EXTERNAL_PACKAGE_SCRIPT": "${sourceDir}/cpack_staging.cmake"
+ },
+ "configurations": ["Debug"]
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "Good",
+ "displayName": "Good Workflow Preset",
+ "description": "This workflow preset works properly.",
+ "vendor": {},
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ },
+ {
+ "type": "build",
+ "name": "default"
+ },
+ {
+ "type": "test",
+ "name": "default"
+ },
+ {
+ "type": "package",
+ "name": "default"
+ }
+ ]
+ },
+ {
+ "name": "BadExitCode",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ },
+ {
+ "type": "build",
+ "name": "default"
+ },
+ {
+ "type": "test",
+ "name": "default"
+ },
+ {
+ "type": "package",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt
new file mode 100644
index 000000000..101491569
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt
@@ -0,0 +1,2 @@
+-- Testing the configure step at [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/GoodUser/build
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake
new file mode 100644
index 000000000..9143e00b3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake
@@ -0,0 +1 @@
+message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}")
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in
new file mode 100644
index 000000000..e71b4ea18
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 6,
+ "workflowPresets": [
+ {
+ "name": "GoodUser",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt
+++ b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-result.txt
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt
new file mode 100644
index 000000000..049ff54c8
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt
@@ -0,0 +1,6 @@
+^Unknown argument -DINVALID_OPTION
+Usage: cmake --workflow \[options\]
+Options:
+ --preset <preset> = Workflow preset to execute\.
+ --list-presets = List available workflow presets\.
+ --fresh = Configure a fresh build tree, removing any existing cache file\.$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stdout.txt
new file mode 100644
index 000000000..10f32932e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stdout.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt
new file mode 100644
index 000000000..57f30a4e0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt
@@ -0,0 +1,4 @@
+^Available workflow presets:
+
+ "default"
+ "with-description" - With Description$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in
new file mode 100644
index 000000000..9a7d5a615
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in
@@ -0,0 +1,30 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ },
+ {
+ "name": "with-description",
+ "displayName": "With Description",
+ "description": "This preset has a description.",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt
new file mode 100644
index 000000000..049ed6bc5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps: Invalid workflow steps$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in
new file mode 100644
index 000000000..27571979e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 6,
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": []
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt
new file mode 100644
index 000000000..c522b84d4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep: Invalid workflow steps$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in
new file mode 100644
index 000000000..235398bef
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 6,
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
new file mode 100644
index 000000000..550600a18
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
@@ -0,0 +1,89 @@
+include(RunCMake)
+
+# Presets do not support legacy VS generator name architecture suffix.
+if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ")
+ set(RunCMake_GENERATOR "${CMAKE_MATCH_1}")
+endif()
+
+function(run_cmake_workflow_presets name)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build")
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+
+ if(NOT RunCMake_TEST_NO_CLEAN)
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+ endif()
+
+ set(RunCMake_TEST_NO_CLEAN TRUE)
+
+ set(CASE_NAME "${name}")
+ set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
+
+ if(NOT CMakePresets_FILE)
+ set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in")
+ endif()
+ if(EXISTS "${CMakePresets_FILE}")
+ configure_file("${CMakePresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY)
+ endif()
+
+ if(NOT CMakeUserPresets_FILE)
+ set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in")
+ endif()
+ if(EXISTS "${CMakeUserPresets_FILE}")
+ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY)
+ endif()
+
+ foreach(ASSET ${CMakePresets_ASSETS})
+ configure_file("${RunCMake_SOURCE_DIR}/${ASSET}.in" "${RunCMake_TEST_SOURCE_DIR}/${ASSET}" @ONLY)
+ endforeach()
+
+ if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-check.cmake")
+ set(RunCMake-check-file "${name}-check.cmake")
+ else()
+ set(RunCMake-check-file "check.cmake")
+ endif()
+
+ if(eq)
+ set(eq 0 PARENT_SCOPE)
+ set(preset_arg "--preset=${name}")
+ else()
+ set(eq 1 PARENT_SCOPE)
+ set(preset_arg "--preset" "${name}")
+ endif()
+ run_cmake_command("${name}" "${CMAKE_COMMAND}" "--workflow" ${preset_arg} ${ARGN})
+endfunction()
+
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
+run_cmake_workflow_presets(UnsupportedVersion)
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+run_cmake_workflow_presets(NoWorkflowSteps)
+run_cmake_workflow_presets(FirstStepNotConfigure)
+run_cmake_workflow_presets(SecondStepConfigure)
+run_cmake_workflow_presets(NonexistentStep)
+run_cmake_workflow_presets(UnreachableStep)
+run_cmake_workflow_presets(WorkflowStepHidden)
+run_cmake_workflow_presets(WorkflowStepDisabled)
+run_cmake_workflow_presets(WorkflowStepInvalidMacro)
+run_cmake_workflow_presets(ConfigureStepMismatch)
+
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Good.json.in")
+set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/GoodUser.json.in")
+set(CMakePresets_ASSETS cpack_staging.cmake)
+run_cmake_workflow_presets(Good)
+run_cmake_workflow_presets(GoodUser)
+run_cmake_workflow_presets(BadExitCode)
+unset(CMakePresets_FILE)
+unset(CMakeUserPresets_FILE)
+unset(CMakePresets_ASSETS)
+
+run_cmake_workflow_presets(ListPresets --list-presets)
+run_cmake_workflow_presets(InvalidOption -DINVALID_OPTION)
+
+set(RunCMake_TEST_NO_CLEAN TRUE)
+file(REMOVE_RECURSE "${RunCMake_BINARY_DIR}/Fresh")
+file(MAKE_DIRECTORY "${RunCMake_BINARY_DIR}/Fresh/build")
+file(WRITE "${RunCMake_BINARY_DIR}/Fresh/build/CMakeCache.txt" "FRESH_CONFIGURE:BOOL=OFF\n")
+run_cmake_workflow_presets(Fresh --fresh)
+unset(RunCMake_TEST_NO_CLEAN)
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt
new file mode 100644
index 000000000..b0ad7d530
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure: Invalid workflow steps$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in
new file mode 100644
index 000000000..44e158259
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in
@@ -0,0 +1,25 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "binaryDir": "${sourceDir}/build",
+ "generator": "@RunCMake_GENERATOR@"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ },
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt
new file mode 100644
index 000000000..425e7196f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep: Workflow step is unreachable from preset's file$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in
new file mode 100644
index 000000000..235398bef
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 6,
+ "workflowPresets": [
+ {
+ "name": "default",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in
new file mode 100644
index 000000000..39b6835a9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in
@@ -0,0 +1,8 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt
new file mode 100644
index 000000000..5cf01aaa5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion: File version must be 6 or higher for workflow preset support$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in
new file mode 100644
index 000000000..4ebaa8efe
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 5,
+ "workflowPresets": []
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt
new file mode 100644
index 000000000..b598b272f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use disabled configure preset in [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled: "default"$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in
new file mode 100644
index 000000000..a3b6783d9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in
@@ -0,0 +1,23 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "condition": {
+ "type": "const",
+ "value": false
+ }
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "WorkflowStepDisabled",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt
new file mode 100644
index 000000000..838ded514
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use hidden configure preset in [^
+]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden: "default"$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in
new file mode 100644
index 000000000..07c4105a9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in
@@ -0,0 +1,20 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "hidden": true
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "WorkflowStepHidden",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt
new file mode 100644
index 000000000..f132a9336
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not evaluate configure preset "default": Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in
new file mode 100644
index 000000000..6aec0e349
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in
@@ -0,0 +1,20 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "binaryDir": "$vendor{invalidMacro}"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "WorkflowStepInvalidMacro",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "default"
+ }
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/check.cmake b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake
new file mode 100644
index 000000000..e79c4f12a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake
@@ -0,0 +1,3 @@
+set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in
new file mode 100644
index 000000000..4030dfb61
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in
@@ -0,0 +1 @@
+message(STATUS "Testing the package step at @RunCMake_TEST_BINARY_DIR@")
diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake
index 9b98ed41f..8904c696f 100644
--- a/Tests/RunCMake/CPack/DEB/Helpers.cmake
+++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake
@@ -97,7 +97,7 @@ function(getMissingShlibsErrorExtra FILE RESULT_VAR)
string(APPEND error_extra "; errors \"${deb_install_files_errors}\"")
endif()
- if(READELF_EXECUTABLE)
+ if(CPACK_READELF_EXECUTABLE)
string(APPEND error_extra "; readelf \"\n")
# Only dynamically linked ELF files are included
@@ -106,7 +106,7 @@ function(getMissingShlibsErrorExtra FILE RESULT_VAR)
if(_FILE MATCHES "ELF.*shared object")
string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}")
- execute_process(COMMAND ${READELF_EXECUTABLE} -d "${CMAKE_MATCH_1}"
+ execute_process(COMMAND ${CPACK_READELF_EXECUTABLE} -d "${CMAKE_MATCH_1}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
diff --git a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake
index 60d02e718..3b02579fb 100644
--- a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake
@@ -14,9 +14,9 @@ function(get_test_prerequirements found_var config_file)
endif()
# optional tool for some tests
- find_program(READELF_EXECUTABLE NAMES readelf)
- if(READELF_EXECUTABLE)
+ find_program(CPACK_READELF_EXECUTABLE NAMES readelf)
+ if(CPACK_READELF_EXECUTABLE)
file(APPEND "${config_file}"
- "\nset(READELF_EXECUTABLE \"${READELF_EXECUTABLE}\")")
+ "\nset(CPACK_READELF_EXECUTABLE \"${CPACK_READELF_EXECUTABLE}\")")
endif()
endfunction()
diff --git a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
index e95cd1516..a4741ba5b 100644
--- a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
@@ -15,9 +15,9 @@ function(get_test_prerequirements found_var config_file)
endif()
# optional tool for some tests
- find_program(OBJDUMP_EXECUTABLE objdump)
- if(OBJDUMP_EXECUTABLE)
+ find_program(CPACK_OBJDUMP_EXECUTABLE objdump)
+ if(CPACK_OBJDUMP_EXECUTABLE)
file(APPEND "${config_file}"
- "\nset(OBJDUMP_EXECUTABLE \"${OBJDUMP_EXECUTABLE}\")")
+ "\nset(CPACK_OBJDUMP_EXECUTABLE \"${CPACK_OBJDUMP_EXECUTABLE}\")")
endif()
endfunction()
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake
index be44b2e33..b0bfc9d02 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake
@@ -1,7 +1,7 @@
function(get_test_prerequirements found_var config_file)
include(${config_file})
- if(READELF_EXECUTABLE)
+ if(CPACK_READELF_EXECUTABLE)
set(${found_var} true PARENT_SCOPE)
endif()
endfunction()
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake
index be44b2e33..b0bfc9d02 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake
@@ -1,7 +1,7 @@
function(get_test_prerequirements found_var config_file)
include(${config_file})
- if(READELF_EXECUTABLE)
+ if(CPACK_READELF_EXECUTABLE)
set(${found_var} true PARENT_SCOPE)
endif()
endfunction()
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake
index 90cfe4467..f5df8a2dd 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake
@@ -2,7 +2,7 @@ function(get_test_prerequirements found_var config_file)
if(SUBTEST_SUFFIX MATCHES ".*single_debug_info")
include(${config_file})
- if(OBJDUMP_EXECUTABLE)
+ if(CPACK_OBJDUMP_EXECUTABLE)
set(${found_var} true PARENT_SCOPE)
endif()
else()
diff --git a/Tests/RunCMake/CTestTimeout/TestTimeout.c b/Tests/RunCMake/CTestTimeout/TestTimeout.c
index 5a008a746..0d534fc06 100644
--- a/Tests/RunCMake/CTestTimeout/TestTimeout.c
+++ b/Tests/RunCMake/CTestTimeout/TestTimeout.c
@@ -1,6 +1,7 @@
#if defined(_WIN32)
# include <windows.h>
#else
+# include <sched.h>
# include <unistd.h>
#endif
diff --git a/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt b/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt
index 7b6eb5384..ce40a7a78 100644
--- a/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt
+++ b/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt
@@ -1,4 +1,4 @@
^(CMake Warning in [^
-]*/Tests/RunCMake/CUDA_architectures/architectures-suffix-build/CMakeFiles/CMakeTmp/CMakeLists.txt:
+]*/Tests/RunCMake/CUDA_architectures/architectures-suffix-build/CMakeFiles/CMakeScratch/TryCompile-[^/]*/CMakeLists.txt:
Clang doesn't support disabling CUDA real code generation.
*)*$
diff --git a/Tests/RunCMake/CXXModules/CMakeLists.txt b/Tests/RunCMake/CXXModules/CMakeLists.txt
new file mode 100644
index 000000000..708d92ce4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.23)
+project(${RunCMake_TEST} NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake
new file mode 100644
index 000000000..cb6f6bdc3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake
@@ -0,0 +1,40 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" export_script)
+
+if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property script inclusion")
+endif ()
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules.cmake" trampoline_script)
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+ endif ()
+else ()
+ if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+ endif ()
+endif ()
+
+set(any_exists 0)
+foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake")
+ continue ()
+ endif ()
+ set(any_exists 1)
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake" config_script)
+
+ if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module per-target property script inclusion")
+ endif ()
+endforeach ()
+
+if (NOT any_exists)
+ list(APPEND RunCMake_TEST_FAILED
+ "No per-configuration target files exist.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt
new file mode 100644
index 000000000..c05b0b482
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at ExportBuildCxxModules.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake
new file mode 100644
index 000000000..850f8dcdd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(export-modules)
+target_sources(export-modules
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(export-modules
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET export-modules
+ PROPERTY EXPORT_NAME export-name)
+
+install(TARGETS export-modules
+ EXPORT exp
+ FILE_SET fs DESTINATION "include/cxx/export-modules")
+
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake
new file mode 100644
index 000000000..9e83fd895
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake
@@ -0,0 +1,35 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/exp.cmake" export_script)
+
+if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property script inclusion")
+endif ()
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules.cmake" trampoline_script)
+
+if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-\*\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+endif ()
+
+set(any_exists 0)
+foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake")
+ continue ()
+ endif ()
+ set(any_exists 1)
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake" config_script)
+
+ if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module per-target property script inclusion")
+ endif ()
+endforeach ()
+
+if (NOT any_exists)
+ list(APPEND RunCMake_TEST_FAILED
+ "No per-configuration target files exist.")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt
new file mode 100644
index 000000000..4fe27a988
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at ExportInstallCxxModules.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake
new file mode 100644
index 000000000..234a4b5a0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(export-modules)
+target_sources(export-modules
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(export-modules
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET export-modules
+ PROPERTY EXPORT_NAME export-name)
+
+install(TARGETS export-modules
+ EXPORT exp
+ FILE_SET fs DESTINATION "include/cxx/export-modules")
+
+install(EXPORT exp
+ DESTINATION "lib/cmake/export-modules"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt
new file mode 100644
index 000000000..d573a02f6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\):
+ target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS"
+ may not have "INTERFACE" visibility
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake
new file mode 100644
index 000000000..03ca17e23
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake
@@ -0,0 +1,8 @@
+add_library(module-header)
+target_sources(module-header
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt
new file mode 100644
index 000000000..1b4ba5d5f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterfaceImported.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake
new file mode 100644
index 000000000..9ff5606de
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake
@@ -0,0 +1,8 @@
+add_library(module-header SHARED IMPORTED)
+target_sources(module-header
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ INTERFACE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt
new file mode 100644
index 000000000..a7ac88ece
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsPrivate.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake
new file mode 100644
index 000000000..ebf9853b2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake
@@ -0,0 +1,13 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module-header
+ sources/cxx-anchor.cxx)
+target_sources(module-header
+ PRIVATE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt
new file mode 100644
index 000000000..a5b4edee7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsPublic.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake
new file mode 100644
index 000000000..3dfccbb55
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake
@@ -0,0 +1,13 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module-header
+ sources/cxx-anchor.cxx)
+target_sources(module-header
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt
new file mode 100644
index 000000000..81a35e8ef
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\) at FileSetModulesInterface.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetModulesInterface.cmake:2 \(target_sources\):
+ target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS"
+ may not have "INTERFACE" visibility
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake
new file mode 100644
index 000000000..24cec3ec1
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake
@@ -0,0 +1,8 @@
+add_library(module)
+target_sources(module
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt
new file mode 100644
index 000000000..4420bbc13
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at FileSetModulesInterfaceImported.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake
new file mode 100644
index 000000000..6640ae943
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake
@@ -0,0 +1,8 @@
+add_library(module SHARED IMPORTED)
+target_sources(module
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ INTERFACE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt
new file mode 100644
index 000000000..03e06cc99
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModulesPrivate.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake
new file mode 100644
index 000000000..ca1898237
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module)
+target_sources(module
+ PRIVATE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt
new file mode 100644
index 000000000..0c110c3a3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModulesPublic.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake
new file mode 100644
index 000000000..58de17425
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module)
+target_sources(module
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/InstallBMI-check.cmake b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake
new file mode 100644
index 000000000..f891c8099
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake
@@ -0,0 +1,24 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi`")
+endif ()
+
+if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script inclusion")
+endif ()
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-optional"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi-optional`")
+endif ()
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-only-debug" OR NOT CMAKE_INSTALL_COMPONENT\)
+ if\(CMAKE_INSTALL_CONFIG_NAME MATCHES "\^\(\[Dd\]\[Ee\]\[Bb\]\[Uu\]\[Gg\]\)\$"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi-only-debug`")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt
new file mode 100644
index 000000000..fc3c7dbbd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMI.cmake:8 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMI.cmake b/Tests/RunCMake/CXXModules/InstallBMI.cmake
new file mode 100644
index 000000000..f0947b47c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI.cmake
@@ -0,0 +1,23 @@
+enable_language(CXX)
+
+add_library(install-bmi)
+target_sources(install-bmi
+ PRIVATE
+ sources/cxx-anchor.cxx)
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ COMPONENT "bmi")
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ EXCLUDE_FROM_ALL
+ COMPONENT "bmi-optional")
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ CONFIGURATIONS Debug
+ COMPONENT "bmi-only-debug")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake
new file mode 100644
index 000000000..32a37ad77
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt
new file mode 100644
index 000000000..44c961fc3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMIGenericArgs.cmake:8 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake
new file mode 100644
index 000000000..8f1714303
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+add_library(install-bmi-generic-args)
+target_sources(install-bmi-generic-args
+ PRIVATE
+ sources/cxx-anchor.cxx)
+
+install(TARGETS install-bmi-generic-args
+ DESTINATION "bin")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake
new file mode 100644
index 000000000..7d13ef089
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake
@@ -0,0 +1,13 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script component for `bmi`")
+endif ()
+
+if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-ignore\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt
new file mode 100644
index 000000000..d9d2c2d58
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMIIgnore.cmake:5 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake
new file mode 100644
index 000000000..f33951106
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+add_library(install-bmi-ignore INTERFACE)
+
+install(TARGETS install-bmi-ignore
+ CXX_MODULES_BMI
+ # An empty destination ignores BMI installation.
+ DESTINATION ""
+ COMPONENT "bmi")
diff --git a/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake
new file mode 100644
index 000000000..412e260d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake
new file mode 100644
index 000000000..0d08c4499
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt
new file mode 100644
index 000000000..ebf7be5cc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoBMIInstall.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake
new file mode 100644
index 000000000..32dc42d98
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake
@@ -0,0 +1,76 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-bmi-install-public)
+target_sources(ninja-bmi-install-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-bmi-install-public
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-bmi-install-public
+ PROPERTY EXPORT_NAME "with-public")
+
+install(TARGETS ninja-bmi-install-public
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal"
+ CXX_MODULES_BMI
+ DESTINATION "lib/cxx/modules/$<CONFIG>"
+ COMPONENT "bmi")
+
+add_library(ninja-bmi-install-private)
+target_sources(ninja-bmi-install-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-bmi-install-private
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-bmi-install-private
+ PROPERTY EXPORT_NAME "with-private")
+
+set(CMAKE_INSTALL_MESSAGE LAZY)
+install(TARGETS ninja-bmi-install-private
+ CXX_MODULES_BMI
+ DESTINATION "lib/cxx/modules/private/$<CONFIG>"
+ PERMISSIONS
+ OWNER_READ OWNER_WRITE
+ GROUP_READ
+ WORLD_READ
+ COMPONENT "bmi")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake
new file mode 100644
index 000000000..77202571d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt
new file mode 100644
index 000000000..e328223fa
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoExport.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake
new file mode 100644
index 000000000..05e7ef7e5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake
@@ -0,0 +1,85 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-exports-public)
+target_sources(ninja-exports-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-public
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-exports-public
+ PROPERTY EXPORT_NAME "with-public")
+
+install(TARGETS ninja-exports-public
+ EXPORT exp
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal")
+
+add_library(ninja-exports-private)
+target_sources(ninja-exports-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-private
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-exports-private
+ PROPERTY EXPORT_NAME "with-private")
+
+install(TARGETS ninja-exports-private
+ EXPORT exp)
+
+# Test multiple build exports.
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export1/export1-targets.cmake"
+ NAMESPACE export1::
+ CXX_MODULES_DIRECTORY "cxx-modules")
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export2/export2-targets.cmake"
+ CXX_MODULES_DIRECTORY "cxx-modules")
+
+# Test multiple install exports.
+install(EXPORT exp
+ DESTINATION "lib/cmake/export1"
+ NAMESPACE export1::
+ CXX_MODULES_DIRECTORY "cxx-modules")
+install(EXPORT exp
+ DESTINATION "lib/cmake/export2"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake
new file mode 100644
index 000000000..b9a1315b7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt
new file mode 100644
index 000000000..ca430ccee
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoFileSet.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake
new file mode 100644
index 000000000..74e729e66
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake
@@ -0,0 +1,59 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-file-sets-public)
+target_sources(ninja-file-sets-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-file-sets-public
+ PRIVATE
+ cxx_std_20)
+
+install(TARGETS ninja-file-sets-public
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal")
+
+add_library(ninja-file-sets-private)
+target_sources(ninja-file-sets-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-file-sets-private
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NoCXX-result.txt b/Tests/RunCMake/CXXModules/NoCXX-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt
new file mode 100644
index 000000000..aa7f406fc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX.cmake:4 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "nocxx" target has C\+\+ module sources but the "CXX" language has not
+ been enabled
+
+(
+CMake Error in CMakeLists.txt:
+( The "nocxx" target has C\+\+ module sources but the "CXX" language has not
+ been enabled
+| The "nocxx" target contains C\+\+ module sources which are not supported by
+ the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX.cmake b/Tests/RunCMake/CXXModules/NoCXX.cmake
new file mode 100644
index 000000000..3c46f9dc0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_library(nocxx)
+target_sources(nocxx
+ PRIVATE
+ sources/c-anchor.c
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
diff --git a/Tests/RunCMake/CXXModules/NoCXX20-result.txt b/Tests/RunCMake/CXXModules/NoCXX20-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt
new file mode 100644
index 000000000..95d73b1ad
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX20.cmake:4 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "nocxx20" target has C\+\+ module sources but is not using at least
+ "cxx_std_20"
+
+(
+CMake Error in CMakeLists.txt:
+( The "nocxx20" target has C\+\+ module sources but is not using at least
+ "cxx_std_20"
+| The "nocxx20" target contains C\+\+ module sources which are not supported by
+ the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX20.cmake b/Tests/RunCMake/CXXModules/NoCXX20.cmake
new file mode 100644
index 000000000..b7372e826
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20.cmake
@@ -0,0 +1,11 @@
+enable_language(CXX)
+
+add_library(nocxx20)
+target_sources(nocxx20
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+set_target_properties(nocxx20
+ PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED ON)
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt
new file mode 100644
index 000000000..aa99af040
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX20ModuleFlag.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "noexperimentalflag" target has C\+\+ module sources but its experimental
+ support has not been requested
+
+(
+CMake Error in CMakeLists.txt:
+( The "noexperimentalflag" target has C\+\+ module sources but its experimental
+ support has not been requested
+| The "noexperimentalflag" target contains C\+\+ module sources which are not
+ supported by the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake
new file mode 100644
index 000000000..79892eed3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+
+unset(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP)
+
+add_library(noexperimentalflag)
+target_sources(noexperimentalflag
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(noexperimentalflag
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt
new file mode 100644
index 000000000..52f781fa3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt
@@ -0,0 +1,30 @@
+CMake Warning \(dev\) at NoDyndepSupport.cmake:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+(CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error:
+ The Ninja generator does not support C\+\+20 modules using Ninja version
+
+ .*
+
+ due to lack of required features. Ninja 1.10 or higher is required.
+
+|CMake Error in CMakeLists.txt:
+ The "nodyndep" target contains C\+\+ module sources which are not supported
+ by the generator
+
+(
+CMake Error in CMakeLists.txt:
+ The "nodyndep" target contains C\+\+ module sources which are not supported
+ by the generator
+
+)*)
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake
new file mode 100644
index 000000000..09544007f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake
@@ -0,0 +1,16 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+if (NOT CMAKE_CXX_STANDARD_DEFAULT)
+ set(CMAKE_CXX_STANDARD_DEFAULT "11")
+endif ()
+
+add_library(nodyndep)
+target_sources(nodyndep
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(nodyndep
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt
new file mode 100644
index 000000000..a93eb400e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt
@@ -0,0 +1,22 @@
+CMake Warning \(dev\) at NotCXXSourceModuleHeaderUnits.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ Target "not-cxx-source" contains the source
+
+ .*/Tests/RunCMake/CXXModules/sources/c-anchor.c
+
+ in a file set of type "CXX_MODULE_HEADER_UNITS" but the source is not
+ classified as a "CXX" source.
+
+
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake
new file mode 100644
index 000000000..af4ddacfa
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake
@@ -0,0 +1,15 @@
+enable_language(C)
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(not-cxx-source)
+target_sources(not-cxx-source
+ PRIVATE
+ sources/cxx-anchor.cxx
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/c-anchor.c)
+target_compile_features(not-cxx-source
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt
new file mode 100644
index 000000000..d341c1f33
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt
@@ -0,0 +1,17 @@
+CMake Warning \(dev\) at NotCXXSourceModules.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ Target "not-cxx-source" contains the source
+
+ .*/Tests/RunCMake/CXXModules/sources/c-anchor.c
+
+ in a file set of type "CXX_MODULES" but the source is not classified as a
+ "CXX" source.
+
+
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake
new file mode 100644
index 000000000..f7a6060df
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake
@@ -0,0 +1,13 @@
+enable_language(C)
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(not-cxx-source)
+target_sources(not-cxx-source
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/c-anchor.c)
+target_compile_features(not-cxx-source
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
new file mode 100644
index 000000000..3f17c1ff0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
@@ -0,0 +1,170 @@
+include(RunCMake)
+
+# For `if (IN_LIST)`
+cmake_policy(SET CMP0057 NEW)
+
+run_cmake(compiler_introspection)
+include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake")
+
+# Test negative cases where C++20 modules do not work.
+run_cmake(NoCXX)
+if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ # This test requires that the compiler be told to compile in an older-than-20
+ # standard. If the compiler forces a standard to be used, skip it.
+ if (NOT forced_cxx_standard)
+ run_cmake(NoCXX20)
+ endif ()
+
+ # This test uses C++20, but another prerequisite is missing, so forced
+ # standards don't matter.
+ run_cmake(NoCXX20ModuleFlag)
+endif ()
+
+if (RunCMake_GENERATOR MATCHES "Ninja")
+ execute_process(
+ COMMAND "${CMAKE_MAKE_PROGRAM}" --version
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE ninja_version
+ ERROR_VARIABLE err
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE)
+
+ if (res)
+ message(WARNING
+ "Failed to determine `ninja` version: ${err}")
+ set(ninja_version "0")
+ endif ()
+endif ()
+
+# Test behavior when the generator does not support C++20 modules.
+if (NOT RunCMake_GENERATOR MATCHES "Ninja" OR
+ ninja_version VERSION_LESS "1.10" OR
+ NOT "cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ run_cmake(NoDyndepSupport)
+ endif ()
+
+ # Bail; the remaining tests require the generator to successfully generate
+ # with C++20 modules in the source list.
+ return ()
+endif ()
+
+set(fileset_types
+ Modules
+ ModuleHeaderUnits)
+set(scopes
+ Interface
+ Private
+ Public)
+foreach (fileset_type IN LISTS fileset_types)
+ foreach (scope IN LISTS scopes)
+ run_cmake("FileSet${fileset_type}${scope}")
+ endforeach ()
+ run_cmake("FileSet${fileset_type}InterfaceImported")
+
+ # Test the error message when a non-C++ source file is found in the source
+ # list.
+ run_cmake("NotCXXSource${fileset_type}")
+endforeach ()
+
+run_cmake(InstallBMI)
+run_cmake(InstallBMIGenericArgs)
+run_cmake(InstallBMIIgnore)
+
+run_cmake(ExportBuildCxxModules)
+run_cmake(ExportInstallCxxModules)
+
+# Generator-specific tests.
+if (RunCMake_GENERATOR MATCHES "Ninja")
+ run_cmake(NinjaDependInfoFileSet)
+ run_cmake(NinjaDependInfoExport)
+ run_cmake(NinjaDependInfoBMIInstall)
+else ()
+ message(FATAL_ERROR
+ "Please add 'DependInfo' tests for the '${RunCMake_GENERATOR}' generator.")
+endif ()
+
+# Actual compilation tests.
+if (NOT CMake_TEST_MODULE_COMPILATION)
+ return ()
+endif ()
+
+function (run_cxx_module_test directory)
+ set(test_name "${directory}")
+ if (NOT ARGN STREQUAL "")
+ list(POP_FRONT ARGN test_name)
+ endif ()
+
+ set(RunCMake_TEST_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/examples/${directory}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/examples/${test_name}-build")
+
+ if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+ else ()
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif ()
+
+ if (RunCMake_CXXModules_INSTALL)
+ set(prefix "${RunCMake_BINARY_DIR}/examples/${test_name}-install")
+ file(REMOVE_RECURSE "${prefix}")
+ list(APPEND RunCMake_TEST_OPTIONS
+ "-DCMAKE_INSTALL_PREFIX=${prefix}")
+ endif ()
+
+ list(APPEND RunCMake_TEST_OPTIONS
+ "-DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}"
+ ${ARGN})
+ run_cmake("examples/${test_name}")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command("examples/${test_name}-build" "${CMAKE_COMMAND}" --build . --config Debug)
+ if (RunCMake_CXXModules_INSTALL)
+ run_cmake_command("examples/${test_name}-install" "${CMAKE_COMMAND}" --build . --target install --config Debug)
+ endif ()
+ run_cmake_command("examples/${test_name}-test" "${CMAKE_CTEST_COMMAND}" -C Debug --output-on-failure)
+endfunction ()
+
+string(REPLACE "," ";" CMake_TEST_MODULE_COMPILATION "${CMake_TEST_MODULE_COMPILATION}")
+
+# Tests which use named modules.
+if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(simple)
+ run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF)
+ run_cxx_module_test(generated)
+ run_cxx_module_test(public-req-private)
+ run_cxx_module_test(deep-chain)
+endif ()
+
+# Tests which use named modules in shared libraries.
+if ("shared" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(library library-shared -DBUILD_SHARED_LIBS=ON)
+endif ()
+
+# Tests which use partitions.
+if ("partitions" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(partitions)
+endif ()
+
+# Tests which use internal partitions.
+if ("internal_partitions" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(internal-partitions)
+endif ()
+
+# Tests which install BMIs
+if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(export-interface-build)
+ run_cxx_module_test(export-bmi-and-interface-build)
+endif ()
+
+# All of the following tests perform installation.
+set(RunCMake_CXXModules_INSTALL 1)
+
+# Tests which install BMIs
+if ("install_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(install-bmi)
+ run_cxx_module_test(install-bmi-and-interfaces)
+
+ if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(export-interface-install)
+ run_cxx_module_test(export-bmi-and-interface-install)
+ endif ()
+endif ()
diff --git a/Tests/RunCMake/CXXModules/check-json.cmake b/Tests/RunCMake/CXXModules/check-json.cmake
new file mode 100644
index 000000000..19d0c8a3c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/check-json.cmake
@@ -0,0 +1,160 @@
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW)
+
+function (json_placeholders in out)
+ string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" in "${in}")
+ if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ string(REPLACE "<CONFIG_DIR>" "${CMAKE_BUILD_TYPE}/" in "${in}")
+ else ()
+ string(REPLACE "<CONFIG_DIR>" "" in "${in}")
+ endif ()
+ if (CMAKE_BUILD_TYPE)
+ string(REPLACE "<CONFIG_FORCE>" "${CMAKE_BUILD_TYPE}" in "${in}")
+ else ()
+ string(REPLACE "<CONFIG_FORCE>" "noconfig" in "${in}")
+ endif ()
+ string(REPLACE "<SOURCE_DIR>" "${RunCMake_SOURCE_DIR}" in "${in}")
+ string(REPLACE "<BINARY_DIR>" "${RunCMake_TEST_BINARY_DIR}" in "${in}")
+ set("${out}" "${in}" PARENT_SCOPE)
+endfunction ()
+
+function (check_json_value path actual_type expect_type actual_value expect_value)
+ if (NOT actual_type STREQUAL expect_type)
+ list(APPEND RunCMake_TEST_FAILED
+ "Type mismatch at ${path}: ${actual_type} vs. ${expect_type}")
+ return ()
+ endif ()
+
+ if (actual_type STREQUAL NULL)
+ # Nothing to check
+ elseif (actual_type STREQUAL BOOLEAN)
+ if (NOT actual_value STREQUAL expect_value)
+ list(APPEND RunCMake_TEST_FAILED
+ "Boolean mismatch at ${path}: ${actual_value} vs. ${expect_value}")
+ endif ()
+ elseif (actual_type STREQUAL NUMBER)
+ if (NOT actual_value EQUAL expect_value)
+ list(APPEND RunCMake_TEST_FAILED
+ "Number mismatch at ${path}: ${actual_value} vs. ${expect_value}")
+ endif ()
+ elseif (actual_type STREQUAL STRING)
+ # Allow some values to be ignored.
+ if (expect_value STREQUAL "<IGNORE>")
+ return ()
+ endif ()
+
+ json_placeholders("${expect_value}" expect_value_expanded)
+ if (NOT actual_value STREQUAL expect_value_expanded)
+ list(APPEND RunCMake_TEST_FAILED
+ "String mismatch at ${path}: ${actual_value} vs. ${expect_value_expanded}")
+ endif ()
+ elseif (actual_type STREQUAL ARRAY)
+ check_json_array("${path}" "${actual_value}" "${expect_value}")
+ elseif (actual_type STREQUAL OBJECT)
+ check_json_object("${path}" "${actual_value}" "${expect_value}")
+ endif ()
+endfunction ()
+
+# Check that two arrays are the same.
+function (check_json_array path actual expect)
+ string(JSON actual_len LENGTH "${actual}")
+ string(JSON expect_len LENGTH "${expect}")
+
+ set(iter_len "${actual_len}")
+ if (actual_len LESS expect_len)
+ list(APPEND RunCMake_TEST_FAILED
+ "Missing array items at ${path}")
+ elseif (expect_len LESS actual_len)
+ list(APPEND RunCMake_TEST_FAILED
+ "Extra array items at ${path}")
+ set(iter_len "${expect_len}")
+ endif ()
+
+ foreach (idx RANGE "${iter_len}")
+ if (idx EQUAL iter_len)
+ break ()
+ endif ()
+
+ set(new_path "${path}[${idx}]")
+ string(JSON actual_type TYPE "${actual}" "${idx}")
+ string(JSON expect_type TYPE "${expect}" "${idx}")
+ string(JSON actual_value GET "${actual}" "${idx}")
+ string(JSON expect_value GET "${expect}" "${idx}")
+ check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
+ endforeach ()
+endfunction ()
+
+# Check that two inner objects are the same.
+function (check_json_object path actual expect)
+ string(JSON actual_len LENGTH "${actual}")
+ string(JSON expect_len LENGTH "${expect}")
+
+ set(actual_keys "")
+ set(expect_keys "")
+ foreach (idx RANGE "${actual_len}")
+ if (idx EQUAL actual_len)
+ break ()
+ endif ()
+
+ string(JSON actual_key MEMBER "${actual}" "${idx}")
+ list(APPEND actual_keys "${actual_key}")
+ endforeach ()
+ foreach (idx RANGE "${expect_len}")
+ if (idx EQUAL expect_len)
+ break ()
+ endif ()
+
+ string(JSON expect_key MEMBER "${expect}" "${idx}")
+ list(APPEND expect_keys "${expect_key}")
+ endforeach ()
+
+ json_placeholders("${expect_keys}" expect_keys_expanded)
+
+ set(actual_keys_missed "${actual_keys}")
+ set(expect_keys_missed "${expect_keys}")
+
+ set(common_keys "")
+ set(expect_keys_stack "${expect_keys}")
+ while (expect_keys_stack)
+ list(POP_BACK expect_keys_stack expect_key)
+ json_placeholders("${expect_key}" expect_key_expanded)
+
+ if (expect_key_expanded IN_LIST actual_keys_missed AND
+ expect_key IN_LIST expect_keys_missed)
+ list(APPEND common_keys "${expect_key}")
+ endif ()
+
+ list(REMOVE_ITEM actual_keys_missed "${expect_key_expanded}")
+ list(REMOVE_ITEM expect_keys_missed "${expect_key}")
+ endwhile ()
+
+ if (actual_keys_missed)
+ string(REPLACE ";" ", " actual_keys_missed_text "${actual_keys_missed}")
+ list(APPEND RunCMake_TEST_FAILED
+ "Missing expected members at ${path}: ${actual_keys_missed_text}")
+ endif ()
+ if (expect_keys_missed)
+ string(REPLACE ";" ", " expect_keys_missed_text "${expect_keys_missed}")
+ list(APPEND RunCMake_TEST_FAILED
+ "Extra unexpected members at ${path}: ${expect_keys_missed_text}")
+ endif ()
+
+ foreach (key IN LISTS common_keys)
+ json_placeholders("${key}" key_expanded)
+ set(new_path "${path}.${key_expanded}")
+ string(JSON actual_type TYPE "${actual}" "${key_expanded}")
+ string(JSON expect_type TYPE "${expect}" "${key}")
+ string(JSON actual_value GET "${actual}" "${key_expanded}")
+ string(JSON expect_value GET "${expect}" "${key}")
+ check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
+ endforeach ()
+endfunction ()
+
+# Check that two JSON objects are the same.
+function (check_json actual expect)
+ check_json_object("" "${actual}" "${expect}")
+endfunction ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
+
+cmake_policy(POP)
diff --git a/Tests/RunCMake/CXXModules/compiler_introspection.cmake b/Tests/RunCMake/CXXModules/compiler_introspection.cmake
new file mode 100644
index 000000000..7a2df3d35
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/compiler_introspection.cmake
@@ -0,0 +1,25 @@
+enable_language(CXX)
+
+set(info "")
+
+# See `Modules/Compiler/MSVC-CXX.cmake` for this. If there is explicitly no
+# default, the feature list is populated to be everything.
+if (DEFINED CMAKE_CXX_STANDARD_DEFAULT AND
+ CMAKE_CXX_STANDARD_DEFAULT STREQUAL "")
+ set(CMAKE_CXX_COMPILE_FEATURES "")
+endif ()
+
+# Detect if the environment forces a C++ standard, let the test selection know.
+set(forced_cxx_standard 0)
+if (CMAKE_CXX_FLAGS MATCHES "-std=")
+ set(forced_cxx_standard 1)
+endif ()
+
+# Forward information about the C++ compile features.
+string(APPEND info "\
+set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\")
+set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\")
+set(forced_cxx_standard \"${forced_cxx_standard}\")
+")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake
new file mode 100644
index 000000000..f99455b47
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake
@@ -0,0 +1,22 @@
+function (check_for_bmi prefix destination name)
+ set(found 0)
+ foreach (ext IN ITEMS gcm)
+ if (EXISTS "${prefix}/${destination}/${name}.${ext}")
+ set(found 1)
+ break ()
+ endif ()
+ endforeach ()
+
+ if (NOT found)
+ message(SEND_ERROR
+ "Failed to find the ${name} BMI")
+ endif ()
+endfunction ()
+
+function (check_for_interface prefix destination subdir name)
+ set(found 0)
+ if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}")
+ message(SEND_ERROR
+ "Failed to find the ${name} module interface")
+ endif ()
+endfunction ()
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake
new file mode 100644
index 000000000..91f399588
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake
@@ -0,0 +1,27 @@
+function (check_for_bmi prefix destination name)
+ set(found 0)
+ foreach (ext IN ITEMS gcm ifc)
+ if (EXISTS "${prefix}/${destination}/${name}.${ext}")
+ set(found 1)
+ break ()
+ endif ()
+ endforeach ()
+
+ if (NOT found)
+ message(SEND_ERROR
+ "Failed to find the ${name} BMI")
+ endif ()
+endfunction ()
+
+function (check_for_interface prefix destination subdir name)
+ set(found 0)
+ if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}")
+ message(SEND_ERROR
+ "Failed to find the ${name} module interface")
+ endif ()
+endfunction ()
+
+function (report_dirs prefix destination)
+ message("prefix: ${prefix}")
+ message("destination: ${destination}")
+endfunction ()
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake
new file mode 100644
index 000000000..381094ea4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake
@@ -0,0 +1,18 @@
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}")
+ message(FATAL_ERROR
+ "The `CMake_TEST_MODULE_COMPILATION_RULES` file must be specified "
+ "for these tests to operate.")
+endif ()
+
+include("${CMake_TEST_MODULE_COMPILATION_RULES}")
+
+if (NOT CMake_TEST_CXXModules_UUID STREQUAL "a246741c-d067-4019-a8fb-3d16b0c9d1d3")
+ message(FATAL_ERROR
+ "The compilation rule file needs updated for changes in the test "
+ "suite. Please see the history for what needs to be updated.")
+endif ()
+
+include(CTest)
+enable_testing()
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt b/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt
new file mode 100644
index 000000000..515b2409d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt
@@ -0,0 +1,66 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_deep_chain CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(a STATIC)
+target_sources(a
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ a.cxx)
+target_compile_features(a PUBLIC cxx_std_20)
+
+add_library(b STATIC)
+target_sources(b
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ b.cxx)
+target_compile_features(b PUBLIC cxx_std_20)
+target_link_libraries(b PUBLIC a)
+
+add_library(c STATIC)
+target_sources(c
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ c.cxx)
+target_compile_features(c PUBLIC cxx_std_20)
+target_link_libraries(c PUBLIC b)
+
+add_library(d STATIC)
+target_sources(d
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ d.cxx)
+target_compile_features(d PUBLIC cxx_std_20)
+target_link_libraries(d PUBLIC c)
+
+add_library(e STATIC)
+target_sources(e
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ e.cxx)
+target_compile_features(e PUBLIC cxx_std_20)
+target_link_libraries(e PUBLIC d)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE e)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx
new file mode 100644
index 000000000..9edaec967
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx
@@ -0,0 +1,6 @@
+export module a;
+
+export int a()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx
new file mode 100644
index 000000000..38ab0c2fe
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx
@@ -0,0 +1,7 @@
+export module b;
+import a;
+
+export int b()
+{
+ return a();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx
new file mode 100644
index 000000000..580a458f3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx
@@ -0,0 +1,7 @@
+export module c;
+import b;
+
+export int c()
+{
+ return b();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx
new file mode 100644
index 000000000..78bc5baa2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx
@@ -0,0 +1,7 @@
+export module d;
+import c;
+
+export int d()
+{
+ return c();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx
new file mode 100644
index 000000000..e0194401b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx
@@ -0,0 +1,7 @@
+export module e;
+import d;
+
+export int e()
+{
+ return d();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx
new file mode 100644
index 000000000..0b7c15df5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx
@@ -0,0 +1,6 @@
+import e;
+
+int main(int argc, char* argv[])
+{
+ return e();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
new file mode 100644
index 000000000..a450b7e5d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
@@ -0,0 +1,56 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_bmi_and_interfaces STATIC)
+target_sources(export_bmi_and_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_bmi_and_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+export(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-targets.cmake"
+ CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_bmi_and_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_source_dir=${CMAKE_CURRENT_SOURCE_DIR}"
+ "-Dexpected_binary_dir=${CMAKE_CURRENT_BINARY_DIR}"
+ "-Dexport_bmi_and_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx
new file mode 100644
index 000000000..7f53271f8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx
new file mode 100644
index 000000000..e0b18728c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx
new file mode 100644
index 000000000..c5b719a33
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
new file mode 100644
index 000000000..b814b3bf7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_bmi_and_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_bmi_and_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG)
+if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)")
+ message(FATAL_ERROR
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
new file mode 100644
index 000000000..a5574fe39
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_bmi_and_interfaces STATIC)
+target_sources(export_bmi_and_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_bmi_and_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+install(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ DESTINATION "lib/cmake/export_bmi_and_interfaces"
+ FILE "export_bmi_and_interfaces-targets.cmake"
+ CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ DESTINATION "lib/cmake/export_bmi_and_interfaces")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_bmi_and_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_source_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
+ "-Dexpected_binary_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/bmi"
+ "-Dexport_bmi_and_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_bmi_and_interfaces"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx
new file mode 100644
index 000000000..7f53271f8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx
new file mode 100644
index 000000000..e0b18728c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx
new file mode 100644
index 000000000..c5b719a33
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
new file mode 100644
index 000000000..db0484d74
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_bmi_and_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_bmi_and_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG)
+if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/importable.(gcm|pcm|ifc)")
+ message(FATAL_ERROR
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
new file mode 100644
index 000000000..80ddaf83e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
@@ -0,0 +1,53 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_interfaces STATIC)
+target_sources(export_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu")
+export(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-targets.cmake")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}"
+ "-Dexport_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx
new file mode 100644
index 000000000..7f53271f8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx
new file mode 100644
index 000000000..e0b18728c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx
new file mode 100644
index 000000000..c5b719a33
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
new file mode 100644
index 000000000..6145210d3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules_set TARGET CXXModules::export_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG SET)
+if (imported_modules_set)
+ message(FATAL_ERROR
+ "Unexpected C++ modules specified.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
new file mode 100644
index 000000000..1dfb6daf7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
@@ -0,0 +1,56 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_interfaces STATIC)
+target_sources(export_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu")
+install(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ DESTINATION "lib/cmake/export_interfaces"
+ FILE "export_interfaces-targets.cmake")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ DESTINATION "lib/cmake/export_interfaces")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
+ "-Dexport_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_interfaces"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx
new file mode 100644
index 000000000..7f53271f8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx
new file mode 100644
index 000000000..e0b18728c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx
new file mode 100644
index 000000000..c5b719a33
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
new file mode 100644
index 000000000..6145210d3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules_set TARGET CXXModules::export_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG SET)
+if (imported_modules_set)
+ message(FATAL_ERROR
+ "Unexpected C++ modules specified.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/generated-stderr.txt b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt
new file mode 100644
index 000000000..b9bbf34f2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:12 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt
new file mode 100644
index 000000000..73f7ff776
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_generated CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/importable.cxx.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx"
+ COPYONLY)
+
+add_executable(generated)
+target_sources(generated
+ PRIVATE
+ main.cxx
+ PRIVATE
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx")
+target_compile_features(generated PUBLIC cxx_std_20)
+
+add_test(NAME generated COMMAND generated)
diff --git a/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in
new file mode 100644
index 000000000..a9287d7fa
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in
@@ -0,0 +1,5 @@
+export module importable;
+
+export int from_import() {
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/generated/main.cxx b/Tests/RunCMake/CXXModules/examples/generated/main.cxx
new file mode 100644
index 000000000..feb38d22e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt
new file mode 100644
index 000000000..efaca0e11
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_install_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(install_bmi_and_interfaces STATIC)
+target_sources(install_bmi_and_interfaces
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(install_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS install_bmi_and_interfaces
+ ARCHIVE DESTINATION "lib"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi"
+ FILE_SET CXX_MODULES DESTINATION "lib/cxx/miu")
+
+add_test(NAME check-for-bmi
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dprefix=${CMAKE_INSTALL_PREFIX}"
+ "-Dbmi_destination=lib/cxx/bmi"
+ "-Dfs_destination=lib/cxx/miu"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake")
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake
new file mode 100644
index 000000000..a8ff1ad6a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake
@@ -0,0 +1,7 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake")
+
+report_dirs("${prefix}" "${bmi_destination}")
+check_for_bmi("${prefix}" "${bmi_destination}" importable)
+
+report_dirs("${prefix}" "${fs_destination}")
+check_for_interface("${prefix}" "${fs_destination}" "" importable.cxx)
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx
new file mode 100644
index 000000000..607680a07
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt
new file mode 100644
index 000000000..4e039f9f2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_install_bmi CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(install_bmi STATIC)
+target_sources(install_bmi
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(install_bmi PUBLIC cxx_std_20)
+
+install(TARGETS install_bmi
+ ARCHIVE DESTINATION "lib"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+
+add_test(NAME check-for-bmi
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dprefix=${CMAKE_INSTALL_PREFIX}"
+ "-Ddestination=lib/cxx/bmi"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake")
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake
new file mode 100644
index 000000000..ff84ed637
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake
@@ -0,0 +1,4 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake")
+
+report_dirs("${prefix}" "${destination}")
+check_for_bmi("${prefix}" "${destination}" importable)
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx
new file mode 100644
index 000000000..607680a07
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt
new file mode 100644
index 000000000..4652aeced
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt
new file mode 100644
index 000000000..f5e9d942d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_internal_partitions CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(internal-partitions)
+generate_export_header(internal-partitions)
+target_sources(internal-partitions
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/internal-partitions_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx
+ partition.cxx)
+target_compile_features(internal-partitions PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE internal-partitions)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx
new file mode 100644
index 000000000..b872ae98c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx
@@ -0,0 +1,9 @@
+export module importable;
+import : internal_partition;
+
+#include "internal-partitions_export.h"
+
+export INTERNAL_PARTITIONS_EXPORT int from_import()
+{
+ return from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx
new file mode 100644
index 000000000..feb38d22e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx
new file mode 100644
index 000000000..b15f53c5a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx
@@ -0,0 +1,6 @@
+module importable : internal_partition;
+
+int from_partition()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt
new file mode 100644
index 000000000..4652aeced
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt
new file mode 100644
index 000000000..4652aeced
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt
new file mode 100644
index 000000000..27fd94f3f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(library)
+generate_export_header(library)
+target_sources(library
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/library_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(library PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE library)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/library/importable.cxx b/Tests/RunCMake/CXXModules/examples/library/importable.cxx
new file mode 100644
index 000000000..72ed0dfd3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+#include "library_export.h"
+
+export LIBRARY_EXPORT int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/library/main.cxx b/Tests/RunCMake/CXXModules/examples/library/main.cxx
new file mode 100644
index 000000000..feb38d22e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt
new file mode 100644
index 000000000..4652aeced
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt
new file mode 100644
index 000000000..3a7b0d4a3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_partitions CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(partitions)
+generate_export_header(partitions)
+target_sources(partitions
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/partitions_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx
+ partition.cxx)
+target_compile_features(partitions PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE partitions)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx
new file mode 100644
index 000000000..d0ac2f47b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx
@@ -0,0 +1,9 @@
+export module importable;
+export import : partition;
+
+#include "partitions_export.h"
+
+export PARTITIONS_EXPORT int from_import()
+{
+ return from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx
new file mode 100644
index 000000000..c5b78c9c5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import() + from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx
new file mode 100644
index 000000000..a47a4fdfd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx
@@ -0,0 +1,8 @@
+export module importable : partition;
+
+#include "partitions_export.h"
+
+export PARTITIONS_EXPORT int from_partition()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt
new file mode 100644
index 000000000..b5f1c5547
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt
@@ -0,0 +1 @@
+CMake Error: Public C\+\+ module source `.*/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx` requires the `priv` C\+\+ module which is provided by a private source
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt
new file mode 100644
index 000000000..600fec4b5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_public_req_private CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(public_req_private)
+target_sources(public_req_private
+ PRIVATE
+ FILE_SET private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ priv.cxx
+ PUBLIC
+ FILE_SET public TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ pub.cxx)
+target_compile_features(public_req_private PUBLIC cxx_std_20)
+
+add_test(NAME cmake-version COMMAND "${CMAKE_COMMAND}" --version)
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx
new file mode 100644
index 000000000..7c000b749
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int g()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx
new file mode 100644
index 000000000..6ff2d2387
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx
@@ -0,0 +1,8 @@
+export module pub;
+
+import priv;
+
+export int f()
+{
+ return g();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/simple-stderr.txt b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt
new file mode 100644
index 000000000..5e4392abc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt
new file mode 100644
index 000000000..442e4256b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_simple CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_executable(simple)
+target_sources(simple
+ PRIVATE
+ main.cxx
+ PRIVATE
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(simple PUBLIC cxx_std_20)
+
+add_test(NAME simple COMMAND simple)
diff --git a/Tests/RunCMake/CXXModules/examples/simple/importable.cxx b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx
new file mode 100644
index 000000000..607680a07
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/simple/main.cxx b/Tests/RunCMake/CXXModules/examples/simple/main.cxx
new file mode 100644
index 000000000..feb38d22e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
new file mode 100644
index 000000000..65f075977
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
@@ -0,0 +1,45 @@
+{
+ "bmi-installation": {
+ "destination": "lib/cxx/modules/private/<CONFIG>",
+ "message-level": "MESSAGE_LAZY",
+ "permissions": " OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ",
+ "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir/install-cxx-module-bmi-<CONFIG_FORCE>.cmake"
+ },
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
new file mode 100644
index 000000000..9c8a8953d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
@@ -0,0 +1,45 @@
+{
+ "bmi-installation": {
+ "destination": "lib/cxx/modules/<CONFIG>",
+ "message-level": "",
+ "permissions": "",
+ "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir/install-cxx-module-bmi-noconfig.cmake"
+ },
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
new file mode 100644
index 000000000..05459815a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
@@ -0,0 +1,73 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-exports-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-exports-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-exports-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export1",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+ "install" : true,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export2",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+ "install" : true,
+ "namespace" : ""
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export1",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+ "install" : false,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export2",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+ "install" : false,
+ "namespace" : ""
+ }
+ ],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
new file mode 100644
index 000000000..adc3ae391
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
@@ -0,0 +1,73 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-exports-public.dir/sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-exports-public.dir/sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-exports-public.dir/sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export1",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+ "install" : true,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export2",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+ "install" : true,
+ "namespace" : ""
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export1",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+ "install" : false,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export2",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+ "install" : false,
+ "namespace" : ""
+ }
+ ],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
new file mode 100644
index 000000000..9ba65688b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
@@ -0,0 +1,40 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
new file mode 100644
index 000000000..46e2cbf98
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
@@ -0,0 +1,40 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/sources/c-anchor.c b/Tests/RunCMake/CXXModules/sources/c-anchor.c
new file mode 100644
index 000000000..c78218892
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/c-anchor.c
@@ -0,0 +1,4 @@
+int c_anchor()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx
new file mode 100644
index 000000000..9c94ec12b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx
@@ -0,0 +1,4 @@
+int cxx_anchor()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-header.h b/Tests/RunCMake/CXXModules/sources/module-header.h
new file mode 100644
index 000000000..982617e5c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-header.h
@@ -0,0 +1,9 @@
+#ifndef module_header_h
+#define module_header_h
+
+inline int h()
+{
+ return 0;
+}
+
+#endif
diff --git a/Tests/RunCMake/CXXModules/sources/module-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-impl.cxx
new file mode 100644
index 000000000..471899916
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-impl.cxx
@@ -0,0 +1,6 @@
+module M;
+
+int f()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx
new file mode 100644
index 000000000..be77b0d54
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx
@@ -0,0 +1,11 @@
+#ifdef _MSC_VER
+// Only MSVC supports this pattern.
+module M : internal_part;
+#else
+module M;
+#endif
+
+int i()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx
new file mode 100644
index 000000000..fa82afbdd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx
@@ -0,0 +1,3 @@
+module M : internal_part;
+
+int i();
diff --git a/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx
new file mode 100644
index 000000000..46d5d9f54
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx
@@ -0,0 +1,13 @@
+#ifdef _MSC_VER
+// Only MSVC supports this pattern.
+module M : part;
+#else
+module M;
+#endif
+
+import M : internal_part;
+
+int p()
+{
+ return i();
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-part.cxx b/Tests/RunCMake/CXXModules/sources/module-part.cxx
new file mode 100644
index 000000000..137c16f29
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-part.cxx
@@ -0,0 +1,3 @@
+export module M : part;
+
+int p();
diff --git a/Tests/RunCMake/CXXModules/sources/module-use.cxx b/Tests/RunCMake/CXXModules/sources/module-use.cxx
new file mode 100644
index 000000000..2d060cdbd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-use.cxx
@@ -0,0 +1,6 @@
+import M;
+
+int main(int argc, char* argv[])
+{
+ return f() + p();
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module.cxx b/Tests/RunCMake/CXXModules/sources/module.cxx
new file mode 100644
index 000000000..a631354cf
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module.cxx
@@ -0,0 +1,5 @@
+export module M;
+export import M : part;
+import M : internal_part;
+
+int f();
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake
index 276158ce0..bfb6f725e 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake
@@ -1,33 +1,27 @@
enable_language (C)
-include(CheckCompilerFlag)
+include(CheckCCompilerFlag)
set(C 1) # test that this is tolerated
-# test that the check uses an isolated locale
-set(_env_LC_ALL "${LC_ALL}")
-set(ENV{LC_ALL} "BAD")
-
-check_compiler_flag(C "-_this_is_not_a_flag_" SHOULD_FAIL)
-if(SHOULD_FAIL)
- message(SEND_ERROR "invalid C compile flag didn't fail.")
+if(NOT CMAKE_C_COMPILER_ID STREQUAL "PathScale")
+ set(DD --)
endif()
-if(CMAKE_C_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
- check_compiler_flag(C "-x c" SHOULD_WORK)
- if(NOT SHOULD_WORK)
- message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c' check failed")
- endif()
+check_c_compiler_flag("${DD}-_this_is_not_a_flag_" C_BOGUS_FLAG)
+if(C_BOGUS_FLAG)
+ message(SEND_ERROR "CHECK_C_COMPILER_FLAG() succeeded, but should have failed")
endif()
-
-if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # LCC C compiler silently ignore -frtti instead of failing, so skip it here.
- check_compiler_flag(C "-frtti" SHOULD_FAIL_RTTI)
- if(SHOULD_FAIL_RTTI)
- message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-frtti' check passed but should have failed")
- endif()
+unset(C_BOGUS_FLAG CACHE)
+if(DEFINED C_BOGUS_FLAG)
+ # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable
+ message(SEND_ERROR "CHECK_C_COMPILER_FLAG shouldn't construct C_BOGUS_FLAG as a normal variable")
endif()
-if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
- message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC")
+ unset(C_STRICT_PROTOTYPES CACHE)
+ CHECK_C_COMPILER_FLAG("-Werror;-Wstrict-prototypes" C_STRICT_PROTOTYPES)
+ if(NOT C_STRICT_PROTOTYPES)
+ message(SEND_ERROR "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
+ endif()
endif()
-set(ENV{LC_ALL} ${_env_LC_ALL})
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake
index dec31ec3a..eb20eb4aa 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake
@@ -1,26 +1,19 @@
enable_language (CXX)
-include(CheckCompilerFlag)
+include(CheckCXXCompilerFlag)
set(CXX 1) # test that this is tolerated
-# test that the check uses an isolated locale
-set(_env_LC_ALL "${LC_ALL}")
-set(ENV{LC_ALL} "BAD")
-
-check_compiler_flag(CXX "-_this_is_not_a_flag_" SHOULD_FAIL)
-if(SHOULD_FAIL)
- message(SEND_ERROR "invalid CXX compile flag didn't fail.")
+if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "PathScale")
+ set(DD --)
endif()
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
- check_compiler_flag(CXX "-x c++" SHOULD_WORK)
- if(NOT SHOULD_WORK)
- message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed")
- endif()
+check_cxx_compiler_flag("${DD}-_this_is_not_a_flag_" CXX_BOGUS_FLAG)
+if(CXX_BOGUS_FLAG)
+ message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed")
endif()
-
-if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
- message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+unset(CXX_BOGUS_FLAG CACHE)
+if(DEFINED CXX_BOGUS_FLAG)
+ # Verify that CHECK_CXX_COMPILER_FLAG didn't construct a normal variable
+ message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG shouldn't construct CXX_BOGUS_FLAG as a normal variable")
endif()
-set(ENV{LC_ALL} ${_env_LC_ALL})
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake
new file mode 100644
index 000000000..276158ce0
--- /dev/null
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake
@@ -0,0 +1,33 @@
+
+enable_language (C)
+include(CheckCompilerFlag)
+
+set(C 1) # test that this is tolerated
+
+# test that the check uses an isolated locale
+set(_env_LC_ALL "${LC_ALL}")
+set(ENV{LC_ALL} "BAD")
+
+check_compiler_flag(C "-_this_is_not_a_flag_" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid C compile flag didn't fail.")
+endif()
+
+if(CMAKE_C_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+ check_compiler_flag(C "-x c" SHOULD_WORK)
+ if(NOT SHOULD_WORK)
+ message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c' check failed")
+ endif()
+endif()
+
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # LCC C compiler silently ignore -frtti instead of failing, so skip it here.
+ check_compiler_flag(C "-frtti" SHOULD_FAIL_RTTI)
+ if(SHOULD_FAIL_RTTI)
+ message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-frtti' check passed but should have failed")
+ endif()
+endif()
+
+if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
+ message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+endif()
+set(ENV{LC_ALL} ${_env_LC_ALL})
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCUDACompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCUDA.cmake
index 681a5466c..681a5466c 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckCUDACompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCUDA.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake
new file mode 100644
index 000000000..dec31ec3a
--- /dev/null
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake
@@ -0,0 +1,26 @@
+
+enable_language (CXX)
+include(CheckCompilerFlag)
+
+set(CXX 1) # test that this is tolerated
+
+# test that the check uses an isolated locale
+set(_env_LC_ALL "${LC_ALL}")
+set(ENV{LC_ALL} "BAD")
+
+check_compiler_flag(CXX "-_this_is_not_a_flag_" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid CXX compile flag didn't fail.")
+endif()
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ check_compiler_flag(CXX "-x c++" SHOULD_WORK)
+ if(NOT SHOULD_WORK)
+ message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed")
+ endif()
+endif()
+
+if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
+ message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+endif()
+set(ENV{LC_ALL} ${_env_LC_ALL})
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckFortranCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagFortran.cmake
index 236f37b54..236f37b54 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckFortranCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagFortran.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagHIP.cmake
index 339ce1865..339ce1865 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagHIP.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckISPCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagISPC.cmake
index 662319ae6..662319ae6 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckISPCCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagISPC.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJC.cmake
index f250f8d49..f250f8d49 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJC.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCXXCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJCXX.cmake
index bc940a629..bc940a629 100644
--- a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCXXCompilerFlag.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJCXX.cmake
diff --git a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
index df2b667cc..b0e025c4f 100644
--- a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
@@ -5,28 +5,30 @@ run_cmake(NonExistentLanguage)
run_cmake(CheckCCompilerFlag)
run_cmake(CheckCXXCompilerFlag)
+run_cmake(CheckCompilerFlagC)
+run_cmake(CheckCompilerFlagCXX)
if (APPLE)
- run_cmake(CheckOBJCCompilerFlag)
- run_cmake(CheckOBJCXXCompilerFlag)
+ run_cmake(CheckCompilerFlagOBJC)
+ run_cmake(CheckCompilerFlagOBJCXX)
endif()
if (CMAKE_Fortran_COMPILER_ID)
- run_cmake(CheckFortranCompilerFlag)
+ run_cmake(CheckCompilerFlagFortran)
endif()
if (CMake_TEST_CUDA)
- run_cmake(CheckCUDACompilerFlag)
+ run_cmake(CheckCompilerFlagCUDA)
endif()
if(CMake_TEST_ISPC)
- run_cmake(CheckISPCCompilerFlag)
+ run_cmake(CheckCompilerFlagISPC)
endif()
if(CMake_TEST_HIP)
- run_cmake(CheckHIPCompilerFlag)
+ run_cmake(CheckCompilerFlagHIP)
endif()
if(APPLE)
- run_cmake_with_options(HeaderpadWorkaround --debug-trycompile)
+ run_cmake(HeaderpadWorkaround)
endif()
diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt
index dc2c3ada9..9a1ba04ad 100644
--- a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt
+++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt
@@ -1,6 +1,6 @@
^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
- IPO is not supported \(no C/CXX/Fortran languages found in ENABLED_LANGUAGES
- global property\)\.
+ IPO is not supported \(no C/CXX/CUDA/Fortran languages found in
+ ENABLED_LANGUAGES global property\)\.
Call Stack \(most recent call first\):
.*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
default-lang-none\.cmake:[0-9]+ \(check_ipo_supported\)
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagC.cmake
index c8e87a474..c8e87a474 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagC.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCUDALinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCUDA.cmake
index 84d6dd92b..84d6dd92b 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckCUDALinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCUDA.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCXX.cmake
index 4e299b989..4e299b989 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCXX.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagFortran.cmake
index bca288ea0..bca288ea0 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagFortran.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagHIP.cmake
index 3bf3b3051..3bf3b3051 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagHIP.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJC.cmake
index fa1d18e38..fa1d18e38 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJC.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJCXX.cmake
index 414efb8cc..414efb8cc 100644
--- a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJCXX.cmake
diff --git a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
index 39fc43097..5915ba1ac 100644
--- a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
@@ -1,22 +1,22 @@
include(RunCMake)
if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU|LCC")
- run_cmake(CheckCLinkerFlag)
- run_cmake(CheckCXXLinkerFlag)
+ run_cmake(CheckLinkerFlagC)
+ run_cmake(CheckLinkerFlagCXX)
if (APPLE)
- run_cmake(CheckOBJCLinkerFlag)
- run_cmake(CheckOBJCXXLinkerFlag)
+ run_cmake(CheckLinkerFlagOBJC)
+ run_cmake(CheckLinkerFlagOBJCXX)
endif()
endif()
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU|LCC")
- run_cmake(CheckFortranLinkerFlag)
+ run_cmake(CheckLinkerFlagFortran)
endif()
if (CMake_TEST_CUDA)
- run_cmake(CheckCUDALinkerFlag)
+ run_cmake(CheckLinkerFlagCUDA)
endif()
if (CMake_TEST_HIP)
- run_cmake(CheckHIPLinkerFlag)
+ run_cmake(CheckLinkerFlagHIP)
endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake
index 4f7362254..7104650cc 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake
@@ -1,15 +1,15 @@
enable_language (C)
-include(CheckSourceCompiles)
+include(CheckCSourceCompiles)
set(C 1) # test that this is tolerated
-check_source_compiles(C "I don't build" SHOULD_FAIL)
+check_c_source_compiles("I don't build" SHOULD_FAIL)
if(SHOULD_FAIL)
message(SEND_ERROR "invalid C source didn't fail.")
endif()
-check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD)
+check_c_source_compiles("int main() {return 0;}" SHOULD_BUILD)
if(NOT SHOULD_BUILD)
message(SEND_ERROR "Test fail for valid C source.")
endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake
index 97c9c30f5..7c9830abc 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake
@@ -1,15 +1,15 @@
enable_language (CXX)
-include(CheckSourceCompiles)
+include(CheckCXXSourceCompiles)
set(CXX 1) # test that this is tolerated
-check_source_compiles(CXX "I don't build" SHOULD_FAIL)
+check_cxx_source_compiles("I don't build" SHOULD_FAIL)
if(SHOULD_FAIL)
message(SEND_ERROR "invalid CXX source didn't fail.")
endif()
-check_source_compiles(CXX [=[
+check_cxx_source_compiles([=[
#include <vector>
int main() {
return 0;
@@ -20,8 +20,8 @@ if(NOT SHOULD_BUILD)
message(SEND_ERROR "Test fail for valid CXX source.")
endif()
-check_source_compiles(CXX "void l(char const (&x)[2]){}; int main() { l(\"\\n\"); return 0;}"
- SHOULD_BUILD_COMPLEX)
+CHECK_CXX_SOURCE_COMPILES("void l(char const (&x)[2]){}; int main() { l(\"\\\\n\"); return 0;}"
+ SHOULD_BUILD_COMPLEX)
if(NOT SHOULD_BUILD_COMPLEX)
message(SEND_ERROR "Test fail for valid CXX complex source.")
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake
index 76a500956..ac43a1ee5 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake
@@ -1,9 +1,14 @@
enable_language (OBJC)
-include(CheckSourceCompiles)
+include(CheckOBJCSourceCompiles)
set(OBJC 1) # test that this is tolerated
-check_source_compiles(OBJC [[
+check_objc_source_compiles("I don't build in Objective-C" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid OBJC source didn't fail.")
+endif()
+
+check_objc_source_compiles([[
#import <Foundation/Foundation.h>
int main() {
NSObject *foo;
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake
index 814237ecc..008895605 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake
@@ -1,9 +1,14 @@
enable_language (OBJCXX)
-include(CheckSourceCompiles)
+include(CheckOBJCXXSourceCompiles)
set(OBJCXX 1) # test that this is tolerated
-check_source_compiles(OBJCXX [[
+check_objcxx_source_compiles("I don't build in Objective-C++" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid OBJCXX source didn't fail.")
+endif()
+
+check_objcxx_source_compiles([[
#include <vector>
#import <Foundation/Foundation.h>
int main() {
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake
new file mode 100644
index 000000000..4f7362254
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake
@@ -0,0 +1,15 @@
+
+enable_language (C)
+include(CheckSourceCompiles)
+
+set(C 1) # test that this is tolerated
+
+check_source_compiles(C "I don't build" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid C source didn't fail.")
+endif()
+
+check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD)
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for valid C source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCUDASourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCUDA.cmake
index 21906499e..21906499e 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckCUDASourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCUDA.cmake
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake
new file mode 100644
index 000000000..97c9c30f5
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake
@@ -0,0 +1,28 @@
+
+enable_language (CXX)
+include(CheckSourceCompiles)
+
+set(CXX 1) # test that this is tolerated
+
+check_source_compiles(CXX "I don't build" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid CXX source didn't fail.")
+endif()
+
+check_source_compiles(CXX [=[
+ #include <vector>
+ int main() {
+ return 0;
+ }
+]=]
+ SHOULD_BUILD)
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for valid CXX source.")
+endif()
+
+check_source_compiles(CXX "void l(char const (&x)[2]){}; int main() { l(\"\\n\"); return 0;}"
+ SHOULD_BUILD_COMPLEX)
+
+if(NOT SHOULD_BUILD_COMPLEX)
+ message(SEND_ERROR "Test fail for valid CXX complex source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckFortranSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesFortran.cmake
index 48dc5255d..48dc5255d 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckFortranSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesFortran.cmake
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesHIP.cmake
index 911a0d7b9..911a0d7b9 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesHIP.cmake
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckISPCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesISPC.cmake
index 74b83c083..74b83c083 100644
--- a/Tests/RunCMake/CheckSourceCompiles/CheckISPCSourceCompiles.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesISPC.cmake
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake
new file mode 100644
index 000000000..76a500956
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake
@@ -0,0 +1,16 @@
+enable_language (OBJC)
+include(CheckSourceCompiles)
+
+set(OBJC 1) # test that this is tolerated
+
+check_source_compiles(OBJC [[
+ #import <Foundation/Foundation.h>
+ int main() {
+ NSObject *foo;
+ return 0;
+ }
+]] SHOULD_BUILD)
+
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for valid OBJC source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake
new file mode 100644
index 000000000..814237ecc
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake
@@ -0,0 +1,19 @@
+enable_language (OBJCXX)
+include(CheckSourceCompiles)
+
+set(OBJCXX 1) # test that this is tolerated
+
+check_source_compiles(OBJCXX [[
+ #include <vector>
+ #import <Foundation/Foundation.h>
+ int main() {
+ std::vector<int> v;
+ NSObject *foo;
+ return 0;
+ }
+]] SHOULD_BUILD)
+
+
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for OBJCXX source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
index 530f133da..df77d3d09 100644
--- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
@@ -6,24 +6,28 @@ run_cmake(UnknownArgument)
run_cmake(CheckCSourceCompiles)
run_cmake(CheckCXXSourceCompiles)
+run_cmake(CheckSourceCompilesC)
+run_cmake(CheckSourceCompilesCXX)
if (APPLE)
run_cmake(CheckOBJCSourceCompiles)
run_cmake(CheckOBJCXXSourceCompiles)
+ run_cmake(CheckSourceCompilesOBJC)
+ run_cmake(CheckSourceCompilesOBJCXX)
endif()
if (CMAKE_Fortran_COMPILER_ID)
- run_cmake(CheckFortranSourceCompiles)
+ run_cmake(CheckSourceCompilesFortran)
endif()
if (CMake_TEST_CUDA)
- run_cmake(CheckCUDASourceCompiles)
+ run_cmake(CheckSourceCompilesCUDA)
endif()
if(CMake_TEST_ISPC)
- run_cmake(CheckISPCSourceCompiles)
+ run_cmake(CheckSourceCompilesISPC)
endif()
if(CMake_TEST_HIP)
- run_cmake(CheckHIPSourceCompiles)
+ run_cmake(CheckSourceCompilesHIP)
endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake
index 96a10274c..c0f946336 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake
@@ -1,15 +1,15 @@
enable_language (C)
-include(CheckSourceRuns)
+include(CheckCSourceRuns)
set(C 1) # test that this is tolerated
-check_source_runs(C "int main() {return 2;}" SHOULD_FAIL)
+check_c_source_runs("int main() {return 2;}" SHOULD_FAIL)
if(SHOULD_FAIL)
- message(SEND_ERROR "C check_source_runs succeeded, but should have failed.")
+ message(SEND_ERROR "check_c_source_runs succeeded, but should have failed.")
endif()
-check_source_runs(C "int main() {return 0;}" SHOULD_RUN)
+check_c_source_runs("int main() {return 0;}" SHOULD_RUN)
if(NOT SHOULD_RUN)
- message(SEND_ERROR "C check_source_runs failed for valid C executable.")
+ message(SEND_ERROR "check_c_source_runs failed for valid C executable.")
endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake
index c4bef6e94..c4c9026c0 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake
@@ -1,15 +1,15 @@
enable_language (CXX)
-include(CheckSourceRuns)
+include(CheckCXXSourceRuns)
set(CXX 1) # test that this is tolerated
-check_source_runs(CXX "int main() {return 2;}" SHOULD_FAIL)
+check_cxx_source_runs("int main() {return 2;}" SHOULD_FAIL)
if(SHOULD_FAIL)
- message(SEND_ERROR "CXX check_source_runs succeeded, but should have failed.")
+ message(SEND_ERROR "check_cxx_source_runs succeeded, but should have failed.")
endif()
-check_source_runs(CXX
+check_cxx_source_runs(
[=[
#include <vector>
int main() {
@@ -18,5 +18,5 @@ check_source_runs(CXX
]=]
SHOULD_RUN)
if(NOT SHOULD_RUN)
- message(SEND_ERROR "CXX check_source_runs failed for valid C executable.")
+ message(SEND_ERROR "check_cxx_source_runs failed for valid C executable.")
endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake
index b8283523d..604b2a1e4 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake
@@ -1,9 +1,14 @@
enable_language (OBJC)
-include(CheckSourceRuns)
+include(CheckOBJCSourceRuns)
set(OBJC 1) # test that this is tolerated
-check_source_runs(OBJC [[
+check_objc_source_runs("int main() {return 2;}" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "check_objc_source_runs succeeded, but should have failed.")
+endif()
+
+check_objc_source_runs([[
#import <Foundation/Foundation.h>
int main() {
NSObject *foo;
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake
index 8a56f139b..b22016666 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake
@@ -1,9 +1,14 @@
enable_language (OBJCXX)
-include(CheckSourceRuns)
+include(CheckOBJCXXSourceRuns)
set(OBJCXX 1) # test that this is tolerated
-check_source_runs(OBJCXX [[
+check_objcxx_source_runs("int main() {return 2;}" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "check_objcxx_source_runs succeeded, but should have failed.")
+endif()
+
+check_objcxx_source_runs([[
#include <vector>
#import <Foundation/Foundation.h>
int main() {
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake
new file mode 100644
index 000000000..96a10274c
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake
@@ -0,0 +1,15 @@
+
+enable_language (C)
+include(CheckSourceRuns)
+
+set(C 1) # test that this is tolerated
+
+check_source_runs(C "int main() {return 2;}" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "C check_source_runs succeeded, but should have failed.")
+endif()
+
+check_source_runs(C "int main() {return 0;}" SHOULD_RUN)
+if(NOT SHOULD_RUN)
+ message(SEND_ERROR "C check_source_runs failed for valid C executable.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCUDASourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCUDA.cmake
index ea5f4f975..ea5f4f975 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckCUDASourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCUDA.cmake
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake
new file mode 100644
index 000000000..c4bef6e94
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake
@@ -0,0 +1,22 @@
+
+enable_language (CXX)
+include(CheckSourceRuns)
+
+set(CXX 1) # test that this is tolerated
+
+check_source_runs(CXX "int main() {return 2;}" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "CXX check_source_runs succeeded, but should have failed.")
+endif()
+
+check_source_runs(CXX
+[=[
+ #include <vector>
+ int main() {
+ return 0;
+ }
+]=]
+ SHOULD_RUN)
+if(NOT SHOULD_RUN)
+ message(SEND_ERROR "CXX check_source_runs failed for valid C executable.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckFortranSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsFortran.cmake
index 50e8ec85f..50e8ec85f 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckFortranSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsFortran.cmake
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsHIP.cmake
index d9fb8c22a..d9fb8c22a 100644
--- a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsHIP.cmake
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake
new file mode 100644
index 000000000..b8283523d
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake
@@ -0,0 +1,16 @@
+enable_language (OBJC)
+include(CheckSourceRuns)
+
+set(OBJC 1) # test that this is tolerated
+
+check_source_runs(OBJC [[
+ #import <Foundation/Foundation.h>
+ int main() {
+ NSObject *foo;
+ return 0;
+ }
+]] SHOULD_BUILD)
+
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for valid OBJC source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake
new file mode 100644
index 000000000..8a56f139b
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake
@@ -0,0 +1,19 @@
+enable_language (OBJCXX)
+include(CheckSourceRuns)
+
+set(OBJCXX 1) # test that this is tolerated
+
+check_source_runs(OBJCXX [[
+ #include <vector>
+ #import <Foundation/Foundation.h>
+ int main() {
+ std::vector<int> v;
+ NSObject *foo;
+ return 0;
+ }
+]] SHOULD_BUILD)
+
+
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for OBJCXX source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
index 478410337..64cecfc0e 100644
--- a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
@@ -6,20 +6,24 @@ run_cmake(UnknownArgument)
run_cmake(CheckCSourceRuns)
run_cmake(CheckCXXSourceRuns)
+run_cmake(CheckSourceRunsC)
+run_cmake(CheckSourceRunsCXX)
if (APPLE)
run_cmake(CheckOBJCSourceRuns)
run_cmake(CheckOBJCXXSourceRuns)
+ run_cmake(CheckSourceRunsOBJC)
+ run_cmake(CheckSourceRunsOBJCXX)
endif()
if (CMAKE_Fortran_COMPILER_ID)
- run_cmake(CheckFortranSourceRuns)
+ run_cmake(CheckSourceRunsFortran)
endif()
if (CMake_TEST_CUDA)
- run_cmake(CheckCUDASourceRuns)
+ run_cmake(CheckSourceRunsCUDA)
endif()
if (CMake_TEST_HIP)
- run_cmake(CheckHIPSourceRuns)
+ run_cmake(CheckSourceRunsHIP)
endif()
diff --git a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
index ee41d9475..5e3fbc478 100644
--- a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
@@ -29,3 +29,4 @@ if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
endif()
endif()
run_tidy(C-bad)
+run_tidy(compdb)
diff --git a/Tests/RunCMake/ClangTidy/compdb.cmake b/Tests/RunCMake/ClangTidy/compdb.cmake
new file mode 100644
index 000000000..f83e0aee9
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/compdb.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+
+# Include a --checks option to confirm that we don't match options that start
+# with --, only a standalone --
+set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -p ${CMAKE_BINARY_DIR} --checks=*)
+
+add_executable(main main.c)
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt
deleted file mode 100644
index 202ef80b6..000000000
--- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-^CMake Warning:
- The "Visual Studio 10 2010" generator is deprecated and will be removed in
- a future version of CMake.
-
- Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt
new file mode 100644
index 000000000..90809420e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning:
+ The "Visual Studio 11 2012" generator is deprecated and will be removed in
+ a future version of CMake.
+
+ Add CMAKE_WARN_VS11=OFF to the cache to disable this warning.$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index 6a932f1e9..1452c9b62 100644
--- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
+++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
@@ -1 +1 @@
-^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":4}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"version":{.*}}$
+^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":4}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
diff --git a/Tests/RunCMake/CommandLine/E_env-equal.cmake b/Tests/RunCMake/CommandLine/E_env-equal.cmake
new file mode 100644
index 000000000..3f18bb65f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env-equal.cmake
@@ -0,0 +1,15 @@
+if (NOT DEFINED ENV{TEST_ENV_EXPECTED})
+ if (NOT DEFINED ENV{TEST_ENV})
+ message(STATUS "TEST_ENV is correctly not set in environment")
+ else ()
+ message(FATAL_ERROR "TEST_ENV is incorrectly set in environment")
+ endif ()
+else ()
+ if (NOT DEFINED ENV{TEST_ENV})
+ message(FATAL_ERROR "TEST_ENV is incorrectly not set in environment")
+ elseif ("$ENV{TEST_ENV}" STREQUAL "$ENV{TEST_ENV_EXPECTED}")
+ message(STATUS "TEST_ENV is correctly set in environment: $ENV{TEST_ENV}")
+ else ()
+ message(FATAL_ERROR "TEST_ENV is incorrectly set in environment!\n\tactual: $ENV{TEST_ENV}\n\texpected: $ENV{TEST_ENV_EXPECTED}")
+ endif ()
+endif ()
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt
new file mode 100644
index 000000000..ccfdeab3d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Error: Unrecognized environment manipulation argument: unknown
+
+cmake -E env: invalid parameter to --modify: TEST_ENV=unknown:$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt
new file mode 100644
index 000000000..ad42f5693
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly set in environment: exp;ect;ed$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt
new file mode 100644
index 000000000..49572a3d3
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly set in environment: exp[;:]ect[;:]ed$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt
new file mode 100644
index 000000000..a60f1bf30
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly set in environment: expected$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt
new file mode 100644
index 000000000..a1d5c0108
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly not set in environment$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt
new file mode 100644
index 000000000..feff1176e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly set in environment: 1$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt
new file mode 100644
index 000000000..a60f1bf30
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly set in environment: expected$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt
new file mode 100644
index 000000000..a1d5c0108
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt
@@ -0,0 +1 @@
+^-- TEST_ENV is correctly not set in environment$
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt
new file mode 100644
index 000000000..8d98f9deb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/CommandLine/P_working-dir.cmake b/Tests/RunCMake/CommandLine/P_working-dir.cmake
index 4ea029382..e2c0378eb 100644
--- a/Tests/RunCMake/CommandLine/P_working-dir.cmake
+++ b/Tests/RunCMake/CommandLine/P_working-dir.cmake
@@ -9,6 +9,11 @@ foreach(d CMAKE_BINARY_DIR CMAKE_CURRENT_BINARY_DIR CMAKE_SOURCE_DIR CMAKE_CURRE
if(EXPECTED_WORKING_DIR STREQUAL "${${d}}")
message(STATUS "${d} is the expected working directory (${EXPECTED_WORKING_DIR})")
else()
- message(FATAL_ERROR "${d} = \"${${d}}\" is not the expected working directory (${EXPECTED_WORKING_DIR})")
+ get_filename_component(resolved "${EXPECTED_WORKING_DIR}" REALPATH)
+ if(resolved STREQUAL "${${d}}")
+ message(STATUS "${d} is the expected working directory (${resolved}) after symlink resolution")
+ else()
+ message(FATAL_ERROR "${d} = \"${${d}}\" is not the expected working directory (${EXPECTED_WORKING_DIR})")
+ endif()
endif()
endforeach()
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index fc05b2d9d..a2eeddf4a 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -744,6 +744,10 @@ run_cmake_command(E_cat-without-double-dash ${CMAKE_COMMAND} -E cat "-file-start
unset(RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
unset(out)
+# Unset environment variables that are used for testing cmake -E
+unset(ENV{TEST_ENV})
+unset(ENV{TEST_ENV_EXPECTED})
+
run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env)
run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1)
run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1)
@@ -758,6 +762,56 @@ file(COPY_FILE "${EXIT_CODE_EXE}" "${RunCMake_BINARY_DIR}/env=${exit_code}")
run_cmake_command(E_env-with-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 -- "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit)
run_cmake_command(E_env-without-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit)
+## Tests of env --modify
+# Repeat the same tests as above
+run_cmake_command(E_env_modify-set ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake)
+run_cmake_command(E_env_modify-unset ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 ${CMAKE_COMMAND} -E env --modify TEST_ENV=unset: ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake)
+run_cmake_command(E_env_modify-with-double-dash ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 -- "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit)
+run_cmake_command(E_env_modify-without-double-dash ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit)
+
+# Test environment modification commands
+run_cmake_command(E_env_modify-reset
+ ${CMAKE_COMMAND} -E env TEST_ENV=expected
+ ${CMAKE_COMMAND} -E env TEST_ENV_EXPECTED=expected TEST_ENV=bad_value --modify TEST_ENV=reset:
+ ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake)
+
+run_cmake_command(E_env_modify-reset-to-unset
+ ${CMAKE_COMMAND} -E env --unset=TEST_ENV --unset=TEST_ENV_EXPECTED
+ ${CMAKE_COMMAND} -E env TEST_ENV=bad_value --modify TEST_ENV=reset:
+ ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake)
+
+run_cmake_command(E_env_modify-string
+ ${CMAKE_COMMAND} -E env TEST_ENV_EXPECTED=expected
+ --modify TEST_ENV=unset:
+ --modify TEST_ENV=string_append:ect
+ --modify TEST_ENV=string_prepend:exp
+ --modify TEST_ENV=string_append:ed
+ ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake)
+
+if (WIN32)
+ set(SEP "\\;")
+else ()
+ set(SEP ":")
+endif ()
+
+run_cmake_command(E_env_modify-path_list
+ ${CMAKE_COMMAND} -E env "TEST_ENV_EXPECTED=exp${SEP}ect${SEP}ed"
+ --modify TEST_ENV=unset:
+ --modify TEST_ENV=path_list_append:ect
+ --modify TEST_ENV=path_list_prepend:exp
+ --modify TEST_ENV=path_list_append:ed
+ ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake)
+
+run_cmake_command(E_env_modify-cmake_list
+ ${CMAKE_COMMAND} -E env "TEST_ENV_EXPECTED=exp\\;ect\\;ed"
+ --modify TEST_ENV=unset:
+ --modify TEST_ENV=cmake_list_append:ect
+ --modify TEST_ENV=cmake_list_prepend:exp
+ --modify TEST_ENV=cmake_list_append:ed
+ ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake)
+
+run_cmake_command(E_env_modify-bad-operation ${CMAKE_COMMAND} -E env --modify TEST_ENV=unknown:)
+
run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .)
run_cmake_command(E_sha1sum-dir ${CMAKE_COMMAND} -E sha1sum .)
run_cmake_command(E_sha224sum-dir ${CMAKE_COMMAND} -E sha224sum .)
@@ -924,6 +978,8 @@ set(RunCMake_TEST_OPTIONS --debug-trycompile)
run_cmake(debug-trycompile)
unset(RunCMake_TEST_OPTIONS)
+run_cmake(trycompile-clean)
+
function(run_cmake_depends)
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_SOURCE_DIR}/cmake_depends")
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/cmake_depends-build")
@@ -941,8 +997,8 @@ set(CMAKE_DEPENDS_CHECK_C
set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"${RunCMake_TEST_SOURCE_DIR}\")
set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\")
")
- run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E cmake_depends
- "Unix Makefiles"
+ run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E env VERBOSE=1
+ ${CMAKE_COMMAND} -E cmake_depends "Unix Makefiles"
${RunCMake_TEST_SOURCE_DIR} ${RunCMake_TEST_SOURCE_DIR}
${RunCMake_TEST_BINARY_DIR} ${RunCMake_TEST_BINARY_DIR}
${RunCMake_TEST_BINARY_DIR}/CMakeFiles/DepTarget.dir/DependInfo.cmake
@@ -1016,9 +1072,9 @@ set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${P
run_cmake(ProfilingTest)
unset(RunCMake_TEST_OPTIONS)
-if(RunCMake_GENERATOR MATCHES "^Visual Studio 10 2010")
- run_cmake_with_options(DeprecateVS10-WARN-ON -DCMAKE_WARN_VS10=ON)
- unset(ENV{CMAKE_WARN_VS10})
- run_cmake(DeprecateVS10-WARN-ON)
- run_cmake_with_options(DeprecateVS10-WARN-OFF -DCMAKE_WARN_VS10=OFF)
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 11 2012")
+ run_cmake_with_options(DeprecateVS11-WARN-ON -DCMAKE_WARN_VS11=ON)
+ unset(ENV{CMAKE_WARN_VS11})
+ run_cmake(DeprecateVS11-WARN-ON)
+ run_cmake_with_options(DeprecateVS11-WARN-OFF -DCMAKE_WARN_VS11=OFF)
endif()
diff --git a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
index 8fe092b4a..cf972a805 100644
--- a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
+++ b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
@@ -1 +1 @@
-^Scanning dependencies of target DepTarget$
+Scanning dependencies of target DepTarget$
diff --git a/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt b/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt
new file mode 100644
index 000000000..e98730063
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Debug Log at [^
+]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\):
+ Executing try_compile \(CMAKE_C_ABI_COMPILED\) in:
+
+ [^
+]*/Tests/RunCMake/CommandLine/debug-trycompile-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)
+ debug-trycompile.cmake:[0-9]+ \(enable_language\)
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CommandLine/debug-trycompile.cmake b/Tests/RunCMake/CommandLine/debug-trycompile.cmake
index a3835a700..9619ba8f1 100644
--- a/Tests/RunCMake/CommandLine/debug-trycompile.cmake
+++ b/Tests/RunCMake/CommandLine/debug-trycompile.cmake
@@ -1,5 +1,8 @@
enable_language(C)
+
# Look for a source tree left by enable_language internal checks.
-if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeLists.txt)
+set(scratch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeScratch)
+file(GLOB_RECURSE remnants ${scratch}/TryCompile-*/CMakeLists.txt)
+if(NOT remnants)
message(FATAL_ERROR "--debug-trycompile should leave the source behind")
endif()
diff --git a/Tests/RunCMake/CommandLine/trycompile-clean.cmake b/Tests/RunCMake/CommandLine/trycompile-clean.cmake
new file mode 100644
index 000000000..11ec2b9bb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/trycompile-clean.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+# Look for a source tree left by enable_language internal checks.
+set(scratch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeScratch)
+file(GLOB_RECURSE remnants ${scratch}/TryCompile-*/*)
+if(remnants)
+ message(FATAL_ERROR "try_compile should not leave artifacts behind")
+endif()
diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
index 84d047982..e6a26052c 100644
--- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
@@ -17,7 +17,8 @@ endfunction()
function(run_compiler_launcher_env lang)
string(REGEX REPLACE "-.*" "" core_lang "${lang}")
- set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+ # Use the noop genexp $<PATH:...> genexp to validate genexp support.
+ set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "$<PATH:CMAKE_PATH,${CMAKE_COMMAND}>;-E;env;USED_LAUNCHER=1")
run_compiler_launcher(${lang})
unset(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER})
endfunction()
diff --git a/Tests/RunCMake/CompilerTest/C-stdout.txt b/Tests/RunCMake/CompilerTest/C-stdout.txt
new file mode 100644
index 000000000..ce5d80eb8
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/C-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working C compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/C.cmake b/Tests/RunCMake/CompilerTest/C.cmake
new file mode 100644
index 000000000..8e9d70cf4
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/C.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_C_ABI_COMPILED FALSE)
+enable_language(C)
diff --git a/Tests/RunCMake/CompilerTest/CMakeLists.txt b/Tests/RunCMake/CompilerTest/CMakeLists.txt
new file mode 100644
index 000000000..aba10165b
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.24)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CompilerTest/CUDA-stdout.txt b/Tests/RunCMake/CompilerTest/CUDA-stdout.txt
new file mode 100644
index 000000000..00d35df88
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/CUDA-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working CUDA compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/CUDA.cmake b/Tests/RunCMake/CompilerTest/CUDA.cmake
new file mode 100644
index 000000000..e8c19a0d3
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/CUDA.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_CUDA_ABI_COMPILED FALSE)
+enable_language(CUDA)
diff --git a/Tests/RunCMake/CompilerTest/CXX-stdout.txt b/Tests/RunCMake/CompilerTest/CXX-stdout.txt
new file mode 100644
index 000000000..513fd85ef
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/CXX-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working CXX compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/CXX.cmake b/Tests/RunCMake/CompilerTest/CXX.cmake
new file mode 100644
index 000000000..e17cc9d05
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/CXX.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_CXX_ABI_COMPILED FALSE)
+enable_language(CXX)
diff --git a/Tests/RunCMake/CompilerTest/Fortran-stdout.txt b/Tests/RunCMake/CompilerTest/Fortran-stdout.txt
new file mode 100644
index 000000000..d871feaa0
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/Fortran-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working Fortran compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/Fortran.cmake b/Tests/RunCMake/CompilerTest/Fortran.cmake
new file mode 100644
index 000000000..8c83bd784
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/Fortran.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_Fortran_ABI_COMPILED FALSE)
+enable_language(Fortran)
diff --git a/Tests/RunCMake/CompilerTest/HIP-stdout.txt b/Tests/RunCMake/CompilerTest/HIP-stdout.txt
new file mode 100644
index 000000000..8b3baa732
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/HIP-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working HIP compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/HIP.cmake b/Tests/RunCMake/CompilerTest/HIP.cmake
new file mode 100644
index 000000000..e56b77a71
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/HIP.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_HIP_ABI_COMPILED FALSE)
+enable_language(HIP)
diff --git a/Tests/RunCMake/CompilerTest/ISPC-stdout.txt b/Tests/RunCMake/CompilerTest/ISPC-stdout.txt
new file mode 100644
index 000000000..7e45c91a2
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/ISPC-stdout.txt
@@ -0,0 +1,3 @@
+-- The ISPC compiler identification is [^
+]*
+-- Configuring done
diff --git a/Tests/RunCMake/CompilerTest/ISPC.cmake b/Tests/RunCMake/CompilerTest/ISPC.cmake
new file mode 100644
index 000000000..3ce7b2874
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/ISPC.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_ISPC_ABI_COMPILED FALSE)
+enable_language(ISPC)
diff --git a/Tests/RunCMake/CompilerTest/OBJC-stdout.txt b/Tests/RunCMake/CompilerTest/OBJC-stdout.txt
new file mode 100644
index 000000000..23f512068
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/OBJC-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working OBJC compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/OBJC.cmake b/Tests/RunCMake/CompilerTest/OBJC.cmake
new file mode 100644
index 000000000..5ec842ca0
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/OBJC.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_OBJC_ABI_COMPILED FALSE)
+enable_language(OBJC)
diff --git a/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt b/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt
new file mode 100644
index 000000000..82919048f
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt
@@ -0,0 +1,2 @@
+-- Check for working OBJCXX compiler: [^
+]* - works
diff --git a/Tests/RunCMake/CompilerTest/OBJCXX.cmake b/Tests/RunCMake/CompilerTest/OBJCXX.cmake
new file mode 100644
index 000000000..49df0aae5
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/OBJCXX.cmake
@@ -0,0 +1,3 @@
+# Pretend the ABI check failed in order to force the fall-back test to run.
+set(CMAKE_OBJCXX_ABI_COMPILED FALSE)
+enable_language(OBJCXX)
diff --git a/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake b/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake
new file mode 100644
index 000000000..2dd9c7fbe
--- /dev/null
+++ b/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake
@@ -0,0 +1,25 @@
+include(RunCMake)
+
+run_cmake(C)
+run_cmake(CXX)
+
+if(CMake_TEST_CUDA)
+ run_cmake(CUDA)
+endif()
+
+if(CMake_TEST_Fortran)
+ run_cmake(Fortran)
+endif()
+
+if(CMake_TEST_HIP)
+ run_cmake(HIP)
+endif()
+
+if(CMake_TEST_ISPC)
+ run_cmake(ISPC)
+endif()
+
+if(CMake_TEST_OBJC)
+ run_cmake(OBJC)
+ run_cmake(OBJCXX)
+endif()
diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake b/Tests/RunCMake/Configure/CopyFileABI-override.cmake
index c633555b6..67f6ed532 100644
--- a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake
+++ b/Tests/RunCMake/Configure/CopyFileABI-override.cmake
@@ -1,5 +1,6 @@
# Change the executable suffix that try_compile will use for
-# COPY_FILE but not inside the test project. This forces failure.
+# COPY_FILE but not inside the test project, to verify
+# we can handle envs that try and break everything
get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE)
if(NOT in_try_compile)
set(CMAKE_EXECUTABLE_SUFFIX .missing)
diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt
index 92fe2330a..6a856a4d0 100644
--- a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt
+++ b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt
@@ -1,4 +1,4 @@
-- Detecting C compiler ABI info
--- Detecting C compiler ABI info - failed.*
+-- Detecting C compiler ABI info - done.*
-- Configuring done
-- Generating done
diff --git a/Tests/RunCMake/Configure/FailCopyFileABI.cmake b/Tests/RunCMake/Configure/CopyFileABI.cmake
index 74efd9720..4eee100ea 100644
--- a/Tests/RunCMake/Configure/FailCopyFileABI.cmake
+++ b/Tests/RunCMake/Configure/CopyFileABI.cmake
@@ -1,2 +1,2 @@
-set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/FailCopyFileABI-override.cmake)
+set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/CopyFileABI-override.cmake)
enable_language(C)
diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake
deleted file mode 100644
index db0cb0a34..000000000
--- a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-set(log "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/CMakeError.log")
-if(EXISTS "${log}")
- file(READ "${log}" error_log)
-else()
- set(error_log "")
-endif()
-string(REPLACE "\r\n" "\n" regex "Cannot copy output executable.*
-to destination specified by COPY_FILE:.*
-Unable to find the executable at any of:
- .*\\.missing")
-if(NOT error_log MATCHES "${regex}")
- string(REGEX REPLACE "\n" "\n " error_log " ${error_log}")
- set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected COPY_FILE failure message:\n${error_log}")
-endif()
diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake
index 9fd4499af..750fa3c2b 100644
--- a/Tests/RunCMake/Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake
@@ -1,9 +1,9 @@
include(RunCMake)
run_cmake(ContinueAfterError)
+run_cmake(CopyFileABI)
run_cmake(CustomTargetAfterError)
run_cmake(ErrorLogs)
-run_cmake(FailCopyFileABI)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RerunCMake-build)
diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt
new file mode 100644
index 000000000..2c223f703
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt
@@ -0,0 +1,6 @@
+.*-- once: configure
+.*-- once: build
+.*-- once: install
+.*-- always: configure
+.*-- always: build
+.*-- always: install
diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt
new file mode 100644
index 000000000..d69749013
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt
@@ -0,0 +1,2 @@
+.*-- always: build
+.*-- always: install
diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake
new file mode 100644
index 000000000..2e5fc6f72
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake
@@ -0,0 +1,20 @@
+include(ExternalProject)
+
+ExternalProject_Add(once
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-configure.cmake
+ BUILD_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-build.cmake
+ INSTALL_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-install.cmake
+ )
+
+ExternalProject_Add(always
+ DEPENDS once
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-configure.cmake
+ BUILD_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-build.cmake
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${CMAKE_CURRENT_LIST_FILE}
+ "${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt"
+ BUILD_BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt"
+ BUILD_ALWAYS 1
+ INSTALL_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-install.cmake
+ )
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 2588d6c59..f152f5b2b 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -177,6 +177,28 @@ if(doSubstitutionTest)
__ep_test_with_build(Substitutions)
endif()
+function(__ep_test_BUILD_ALWAYS)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BUILD_ALWAYS-build)
+ run_cmake(BUILD_ALWAYS)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(STATUS "once: configure")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(STATUS "once: build")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(STATUS "once: install")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(STATUS "always: configure")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-build.cmake" [[message(STATUS "always: build")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-install.cmake" [[message(STATUS "always: install")]])
+ run_cmake_command(BUILD_ALWAYS-build1 ${CMAKE_COMMAND} --build . --target always)
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(FATAL_ERROR "once: configure should not run again")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(FATAL_ERROR "once: build should not run again")]])
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(FATAL_ERROR "once: install should not run again")]])
+ if(NOT RunCMake_GENERATOR MATCHES "^(Xcode|Visual Studio 9 )")
+ # The Xcode and VS 9 build systems decide to run this every time.
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(FATAL_ERROR "always: configure should not run again")]])
+ endif()
+ run_cmake_command(BUILD_ALWAYS-build2 ${CMAKE_COMMAND} --build . --target always)
+endfunction()
+__ep_test_BUILD_ALWAYS()
+
function(__ep_test_CONFIGURE_HANDLED_BY_BUILD)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CONFIGURE_HANDLED_BY_BUILD-build)
run_cmake(CONFIGURE_HANDLED_BY_BUILD)
diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
index 28b8570d0..3b095a633 100644
--- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
@@ -38,9 +38,15 @@ run_cmake(exact_1.2.3.5)
unset(RunCMake_DEFAULT_stderr)
# check if searching for a version 0 works
-list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0")
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0")
run_cmake(exact_0_matching)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=")
+run_cmake(empty_version)
+
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}")
+run_cmake(exact_1_no_version_var)
+
# check custom error message
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCustomMessage_VERSION=1.2.3.4")
run_cmake(custom_message_1)
diff --git a/Tests/RunCMake/FPHSA/empty_version-result.txt b/Tests/RunCMake/FPHSA/empty_version-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/empty_version-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/empty_version-stderr.txt b/Tests/RunCMake/FPHSA/empty_version-stderr.txt
new file mode 100644
index 000000000..3b60c7aac
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/empty_version-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Error at [^
+]*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+ Could NOT find Pseudo: \(Required is at least version "1"\) \(found TRUE\)
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(_FPHSA_FAILURE_MESSAGE\)
+ FindPseudo.cmake:[0-9]+ \(find_package_handle_standard_args\)
+ empty_version.cmake:[0-9]+ \(find_package\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/FPHSA/empty_version.cmake b/Tests/RunCMake/FPHSA/empty_version.cmake
new file mode 100644
index 000000000..7b7ff34f9
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/empty_version.cmake
@@ -0,0 +1 @@
+find_package(Pseudo 1 REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt b/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt
new file mode 100644
index 000000000..7cbdf6ea6
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt
@@ -0,0 +1 @@
+-- Found Pseudo: TRUE \(Required is at least version "1"\)
diff --git a/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake b/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake
new file mode 100644
index 000000000..7b7ff34f9
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake
@@ -0,0 +1 @@
+find_package(Pseudo 1 REQUIRED)
diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt
new file mode 100644
index 000000000..f319e010f
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(barnonsys STATIC bar.cpp)
+add_executable(foononsys foo.cpp)
diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp b/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp b/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt
new file mode 100644
index 000000000..60c682020
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt
@@ -0,0 +1,20 @@
+project(SystemSub NONE)
+
+FetchContent_Declare(
+ SubSub1
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/SubSub1
+ SYSTEM
+)
+FetchContent_Declare(
+ SubSub2
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/SubSub2
+)
+
+FetchContent_MakeAvailable(SubSub1 SubSub2)
+
+add_library(bar STATIC bar.cpp)
+
+add_library(foo STATIC foo.cpp)
+set_target_properties(foo PROPERTIES SYSTEM OFF)
+
+add_executable(zot zot.cpp)
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt
new file mode 100644
index 000000000..291339b8e
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(subsub1bar STATIC bar.cpp)
+
+add_library(subsub1foo STATIC foo.cpp)
+set_target_properties(subsub1foo PROPERTIES SYSTEM OFF)
+
+add_executable(subsub1zot zot.cpp)
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt
new file mode 100644
index 000000000..5755742d7
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(subsub2bar STATIC bar.cpp)
+
+add_library(subsub2foo STATIC foo.cpp)
+set_target_properties(subsub2foo PROPERTIES SYSTEM OFF)
+
+add_executable(subsub2zot zot.cpp)
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp
diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp
diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
index a7ccf8355..bb27491b6 100644
--- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
@@ -8,6 +8,7 @@ run_cmake(FirstDetailsWin)
run_cmake(DownloadTwice)
run_cmake(DownloadFile)
run_cmake(SameGenerator)
+run_cmake(System)
run_cmake(VarDefinitions)
run_cmake(VarPassthroughs)
run_cmake(GetProperties)
diff --git a/Tests/RunCMake/FetchContent/System.cmake b/Tests/RunCMake/FetchContent/System.cmake
new file mode 100644
index 000000000..c10e2af49
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/System.cmake
@@ -0,0 +1,37 @@
+enable_language(CXX)
+
+include(FetchContent)
+
+FetchContent_Declare(
+ IncludesSystem
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/IncludesSystem
+ SYSTEM
+)
+FetchContent_MakeAvailable(IncludesSystem)
+
+FetchContent_Declare(
+ IncludesNonSystem
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/IncludesNonSystem
+)
+FetchContent_MakeAvailable(IncludesNonSystem)
+
+function(check_target_system target expected_value)
+ get_target_property(var ${target} SYSTEM)
+ if ((var AND NOT expected_value) OR (NOT var AND expected_value))
+ message(SEND_ERROR "\
+The 'SYSTEM' property of ${target} should be ${expected_value}, \
+but got ${var}")
+ endif()
+endfunction()
+
+check_target_system(foo OFF)
+check_target_system(bar ON)
+check_target_system(zot ON)
+check_target_system(subsub1foo OFF)
+check_target_system(subsub1bar ON)
+check_target_system(subsub1zot ON)
+check_target_system(subsub2foo OFF)
+check_target_system(subsub2bar ON)
+check_target_system(subsub2zot ON)
+check_target_system(foononsys OFF)
+check_target_system(barnonsys OFF)
diff --git a/Tests/RunCMake/FileAPI/CMakeLists.txt b/Tests/RunCMake/FileAPI/CMakeLists.txt
index 44025d3bd..9a66cde9b 100644
--- a/Tests/RunCMake/FileAPI/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPI/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 3.12)
+cmake_minimum_required(VERSION 3.13)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FileAPI/ClientStateful-check.py b/Tests/RunCMake/FileAPI/ClientStateful-check.py
index f3d20d13e..28679bbce 100644
--- a/Tests/RunCMake/FileAPI/ClientStateful-check.py
+++ b/Tests/RunCMake/FileAPI/ClientStateful-check.py
@@ -108,7 +108,11 @@ def check_query_json_empty(q):
check_error_re(q, "value, object or array expected")
def check_query_json_extra(q):
- check_error_re(q, "Extra non-whitespace after JSON value")
+ if bool(os.environ.get("CMake_JSONCPP_PRE_1_7_5", "")) and is_dict(q) and sorted(q.keys()) == ["responses"]:
+ # jsoncpp < 1.7.5 did not diagnose extra non-whitespace characters
+ check_error(q["responses"], "'requests' member missing")
+ else:
+ check_error_re(q, "Extra non-whitespace after JSON value")
def check_query_not_file(q):
check_error_re(q, "failed to read from file")
diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
index 61dce17bd..961b73a6f 100644
--- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
@@ -39,6 +39,10 @@ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release\\;MinSizeRel\\;RelWithDebInfo")
endif()
+if(JsonCpp_VERSION_STRING AND JsonCpp_VERSION_STRING VERSION_LESS 1.7.5)
+ set(ENV{CMake_JSONCPP_PRE_1_7_5} 1)
+endif()
+
run_cmake(Nothing)
run_cmake(Empty)
run_cmake(EmptyClient)
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index d5f596e70..b7623de2d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -213,6 +213,16 @@ def check_directory(c):
assert is_int(at["index"])
assert c["targets"][at["index"]]["name"] == et["index"]
+ if e.get("cxxModuleBmiTarget", None) is not None:
+ expected_keys.append("cxxModuleBmiTarget")
+ et = e["cxxModuleBmiTarget"]
+ at = a["cxxModuleBmiTarget"]
+ assert is_dict(at)
+ assert sorted(at.keys()) == ["id", "index"]
+ assert matches(at["id"], et["id"])
+ assert is_int(at["index"])
+ assert c["targets"][at["index"]]["name"] == et["index"]
+
if e["backtrace"] is not None:
expected_keys.append("backtrace")
check_backtrace(d, a["backtrace"], e["backtrace"])
@@ -654,6 +664,7 @@ def gen_check_directories(c, g):
read_codemodel_json_data("directories/dir_dir.json"),
read_codemodel_json_data("directories/external.json"),
read_codemodel_json_data("directories/fileset.json"),
+ read_codemodel_json_data("directories/subdir.json"),
]
if matches(g["name"], "^Visual Studio "):
@@ -712,6 +723,7 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/c_shared_exe.json"),
read_codemodel_json_data("targets/c_static_lib.json"),
read_codemodel_json_data("targets/c_static_exe.json"),
+ read_codemodel_json_data("targets/c_subdir.json"),
read_codemodel_json_data("targets/all_build_cxx.json"),
read_codemodel_json_data("targets/zero_check_cxx.json"),
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
index 6514910a8..de8b1779e 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
@@ -10,7 +10,7 @@
"^cxx_alias_exe::@53632cba2752272bb008$"
],
"projectName": "Alias",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json
index c89e4f9dd..e57191cb4 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json
@@ -10,7 +10,7 @@
"^custom_tgt::@c11385ffed57b860da63$"
],
"projectName": "Custom",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json
index 8052c1a55..28f2b9933 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json
@@ -16,7 +16,7 @@
"^cxx_static_lib::@a56b12a3f5c0529fb296$"
],
"projectName": "Cxx",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": true,
"installers": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
index 8509f084c..2a3756e75 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
@@ -7,7 +7,7 @@
],
"targetIds": null,
"projectName": "codemodel-v2",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json
index 27184cd5e..12677f27f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json
@@ -5,7 +5,7 @@
"childSources": null,
"targetIds": null,
"projectName": "codemodel-v2",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
index 6d2952d14..f1199c36b 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
@@ -9,7 +9,7 @@
"^generated_exe::@[0-9a-f]+$"
],
"projectName": "External",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": true,
"installers": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json
index 4774a13e9..c4df2ec70 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json
@@ -8,7 +8,7 @@
"^c_headers_2::@6b8db101d64c125f29fe$"
],
"projectName": "codemodel-v2",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": true,
"installers": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
index 92b952640..8210d7fef 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
@@ -13,7 +13,7 @@
"^link_imported_static_exe::@ba7eb709d0b48779c6c8$"
],
"projectName": "Imported",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": true,
"installers": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
index 90664dc72..08edd649a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
@@ -9,7 +9,7 @@
"^iface_srcs::@25b7fa8ea00134654b85$"
],
"projectName": "Interface",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json
new file mode 100644
index 000000000..996da471c
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json
@@ -0,0 +1,11 @@
+{
+ "source": "^subdir$",
+ "build": "^subdir$",
+ "parentSource": "^\\.$",
+ "childSources": null,
+ "targetIds": null,
+ "projectName": "codemodel-v2",
+ "minimumCMakeVersion": "3.13",
+ "hasInstallRule": null,
+ "installers": []
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
index e7b146f32..aed07e265 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
@@ -11,7 +11,8 @@
"^object$",
"^.*/Tests/RunCMake/FileAPIExternalSource$",
"^dir$",
- "^fileset$"
+ "^fileset$",
+ "^subdir$"
],
"targetIds": [
"^ALL_BUILD::@6890427a1f51a3e7e1df$",
@@ -22,10 +23,11 @@
"^c_shared_lib::@6890427a1f51a3e7e1df$",
"^c_static_exe::@6890427a1f51a3e7e1df$",
"^c_static_lib::@6890427a1f51a3e7e1df$",
+ "^c_subdir::@6890427a1f51a3e7e1df$",
"^interface_exe::@6890427a1f51a3e7e1df$"
],
"projectName": "codemodel-v2",
- "minimumCMakeVersion": "3.12",
+ "minimumCMakeVersion": "3.13",
"hasInstallRule": true,
"installers": [
{
@@ -48,7 +50,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 39,
+ "line": 42,
"command": "install",
"hasParent": true
},
@@ -93,7 +95,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -141,7 +143,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -186,7 +188,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -230,7 +232,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -274,7 +276,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 47,
+ "line": 50,
"command": "install",
"hasParent": true
},
@@ -321,7 +323,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 49,
+ "line": 52,
"command": "install",
"hasParent": true
},
@@ -366,7 +368,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 50,
+ "line": 53,
"command": "install",
"hasParent": true
},
@@ -415,7 +417,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 51,
+ "line": 54,
"command": "install",
"hasParent": true
},
@@ -467,7 +469,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 52,
+ "line": 55,
"command": "install",
"hasParent": true
},
@@ -516,7 +518,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 53,
+ "line": 56,
"command": "install",
"hasParent": true
},
@@ -558,7 +560,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 54,
+ "line": 57,
"command": "install",
"hasParent": true
},
@@ -600,7 +602,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 55,
+ "line": 58,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
index 0d6c4a16d..151c0a81b 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
@@ -14,7 +14,8 @@
"^\\.$",
"^dir$",
"^dir/dir$",
- "^fileset$"
+ "^fileset$",
+ "^subdir$"
],
"targetIds": [
"^ALL_BUILD::@6890427a1f51a3e7e1df$",
@@ -26,6 +27,7 @@
"^c_shared_exe::@6890427a1f51a3e7e1df$",
"^c_static_lib::@6890427a1f51a3e7e1df$",
"^c_static_exe::@6890427a1f51a3e7e1df$",
+ "^c_subdir::@6890427a1f51a3e7e1df$",
"^c_headers_1::@6b8db101d64c125f29fe$",
"^c_headers_2::@6b8db101d64c125f29fe$"
]
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
index 4e772a7f7..0d45d076f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
@@ -96,6 +96,10 @@
"backtrace": null
},
{
+ "id": "^c_subdir::@6890427a1f51a3e7e1df$",
+ "backtrace": null
+ },
+ {
"id": "^c_static_exe::@6890427a1f51a3e7e1df$",
"backtrace": null
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
index 3c9ace3b1..339240498 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
@@ -27,7 +27,7 @@
]
},
{
- "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.c)?\\.o(bj)?$",
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(object|build/c_object_lib\\.build)/.*/empty(\\.c)?\\.o(bj)?$",
"isGenerated": true,
"sourceGroupName": "Object Libraries",
"compileGroupLanguage": null,
@@ -57,7 +57,7 @@
{
"name": "Object Libraries",
"sourcePaths": [
- "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.c)?\\.o(bj)?$"
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(object|build/c_object_lib\\.build)/.*/empty(\\.c)?\\.o(bj)?$"
]
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
index e3a20df3a..1917f92ce 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
@@ -64,7 +64,7 @@
"nameOnDisk": null,
"artifacts": [
{
- "path": "^object/.*/empty(\\.c)?\\.o(bj)?$",
+ "path": "^(object|build/c_object_lib\\.build)/.*/empty(\\.c)?\\.o(bj)?$",
"_dllExtra": false
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
index b4318ddfd..9a210ff60 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
@@ -115,7 +115,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -145,7 +145,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -175,7 +175,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 47,
+ "line": 50,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json
new file mode 100644
index 000000000..12ec917e5
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json
@@ -0,0 +1,150 @@
+{
+ "name": "c_subdir",
+ "id": "^c_subdir::@6890427a1f51a3e7e1df$",
+ "directorySource": "^\\.$",
+ "projectName": "codemodel-v2",
+ "type": "STATIC_LIBRARY",
+ "isGeneratorProvided": null,
+ "sources": [
+ {
+ "path": "^subdir/empty\\.c$",
+ "isGenerated": null,
+ "sourceGroupName": "Source Files",
+ "compileGroupLanguage": "C",
+ "backtrace": [
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": 4,
+ "command": "target_sources",
+ "hasParent": true
+ },
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "Source Files",
+ "sourcePaths": [
+ "^subdir/empty\\.c$"
+ ]
+ }
+ ],
+ "compileGroups": [
+ {
+ "language": "C",
+ "sourcePaths": [
+ "^subdir/empty\\.c$"
+ ],
+ "includes": [
+ {
+ "path": "^.*/Tests/RunCMake/FileAPI/subdir$",
+ "isSystem": null,
+ "backtrace": [
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": 2,
+ "command": "target_include_directories",
+ "hasParent": true
+ },
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "defines": [
+ {
+ "define": "SUBDIR",
+ "backtrace": [
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": 1,
+ "command": "target_compile_definitions",
+ "hasParent": true
+ },
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "compileCommandFragments": null
+ }
+ ],
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 17,
+ "command": "add_library",
+ "hasParent": true
+ },
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": null,
+ "command": null,
+ "hasParent": true
+ },
+ {
+ "file": "^CMakeLists\\.txt$",
+ "line": 3,
+ "command": "include",
+ "hasParent": true
+ },
+ {
+ "file": "^CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": "^(lib)?c_subdir\\.(a|lib)$",
+ "artifacts": [
+ {
+ "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?c_subdir\\.(a|lib)$",
+ "_dllExtra": false
+ }
+ ],
+ "build": "^\\.$",
+ "source": "^\\.$",
+ "install": null,
+ "link": null,
+ "archive": {
+ "lto": null
+ },
+ "dependencies": [
+ {
+ "id": "^c_lib::@6890427a1f51a3e7e1df$",
+ "backtrace": [
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": 3,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^subdir/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+ "backtrace": null
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
index 5769f0cda..16d074aa7 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
@@ -136,7 +136,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 39,
+ "line": 42,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
index 119c91d42..e8d62188a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
@@ -27,7 +27,7 @@
]
},
{
- "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.cxx)?\\.o(bj)?$",
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(object|build/cxx_object_lib\\.build)/.*/empty(\\.cxx)?\\.o(bj)?$",
"isGenerated": true,
"sourceGroupName": "Object Libraries",
"compileGroupLanguage": null,
@@ -57,7 +57,7 @@
{
"name": "Object Libraries",
"sourcePaths": [
- "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.cxx)?\\.o(bj)?$"
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(object|build/cxx_object_lib\\.build)/.*/empty(\\.cxx)?\\.o(bj)?$"
]
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
index 8e99f7d6a..24b391b24 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
@@ -64,7 +64,7 @@
"nameOnDisk": null,
"artifacts": [
{
- "path": "^object/.*/empty(\\.cxx)?\\.o(bj)?$",
+ "path": "^(object|build/cxx_object_lib\\.build)/.*/empty(\\.cxx)?\\.o(bj)?$",
"_dllExtra": false
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
index 1fe4d678c..03f4cb90e 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
@@ -91,7 +91,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -121,7 +121,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 45,
"command": "install",
"hasParent": true
},
@@ -151,7 +151,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 47,
+ "line": 50,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
index 019eb8762..09db21601 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
@@ -14,6 +14,9 @@ add_library(c_static_lib STATIC empty.c)
add_executable(c_static_exe empty.c)
target_link_libraries(c_static_exe PRIVATE c_static_lib)
+add_library(c_subdir STATIC)
+add_subdirectory(subdir)
+
add_subdirectory(cxx)
add_subdirectory(alias)
add_subdirectory(object)
diff --git a/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt b/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt
new file mode 100644
index 000000000..b8f4550d8
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt
@@ -0,0 +1,4 @@
+target_compile_definitions(c_subdir PRIVATE SUBDIR)
+target_include_directories(c_subdir PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(c_subdir PRIVATE c_lib)
+target_sources(c_subdir PRIVATE empty.c)
diff --git a/Tests/RunCMake/FileAPI/subdir/empty.c b/Tests/RunCMake/FileAPI/subdir/empty.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/subdir/empty.c
diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
index 3908f4243..dad0dd36c 100644
--- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
@@ -13,6 +13,9 @@ run_cmake(zip)
# Extracting only selected files or directories
run_cmake(zip-filtered)
+run_cmake(create-missing-args)
+run_cmake(extract-missing-args)
+
run_cmake(unsupported-format)
run_cmake(zip-with-bad-compression)
run_cmake(7zip-with-bad-compression)
diff --git a/Tests/RunCMake/File_Archive/create-missing-args-result.txt b/Tests/RunCMake/File_Archive/create-missing-args-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
new file mode 100644
index 000000000..fd026f929
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
@@ -0,0 +1,19 @@
+^CMake Error at create-missing-args.cmake:[0-9]+ \(file\):
+ Error after keyword "COMPRESSION":
+
+ missing required value
+
+ Error after keyword "COMPRESSION_LEVEL":
+
+ missing required value
+
+ Error after keyword "FORMAT":
+
+ missing required value
+
+ Error after keyword "OUTPUT":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Archive/create-missing-args.cmake b/Tests/RunCMake/File_Archive/create-missing-args.cmake
new file mode 100644
index 000000000..a0c84d2dd
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args.cmake
@@ -0,0 +1,8 @@
+file(ARCHIVE_CREATE
+ OUTPUT # missing output path
+ FORMAT # missing output format
+ COMPRESSION # missing compression type
+ COMPRESSION_LEVEL # missing compression level
+ MTIME # missing modification time
+ PATHS # no paths
+ )
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-result.txt b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
new file mode 100644
index 000000000..0c93ecef2
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Error at extract-missing-args.cmake:[0-9]+ \(file\):
+ Error after keyword "DESTINATION":
+
+ missing required value
+
+ Error after keyword "INPUT":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args.cmake b/Tests/RunCMake/File_Archive/extract-missing-args.cmake
new file mode 100644
index 000000000..21c5d997a
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args.cmake
@@ -0,0 +1,5 @@
+file(ARCHIVE_EXTRACT
+ INPUT # missing input
+ DESTINATION # missing destination
+ PATTERNS # no patterns
+ )
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
index a6ea314d5..72292f9b5 100644
--- a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
- file CONFIGURE CONTENT option needs a value.
+ Error after keyword "CONTENT":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
index b5a924c13..d793f4830 100644
--- a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
- file CONFIGURE OUTPUT option needs a value.
+ Error after keyword "OUTPUT":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-result.txt b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
new file mode 100644
index 000000000..2e8dd9a74
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgContent.cmake:[0-9]+ \(file\):
+ file CONFIGURE CONTENT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgContent.cmake b/Tests/RunCMake/File_Configure/NoArgContent.cmake
new file mode 100644
index 000000000..cf52c4667
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent.cmake
@@ -0,0 +1 @@
+file(CONFIGURE OUTPUT "")
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-result.txt b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
new file mode 100644
index 000000000..53de48b0a
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgOutput.cmake:[0-9]+ \(file\):
+ file CONFIGURE OUTPUT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput.cmake b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
new file mode 100644
index 000000000..77e9cdc8f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
@@ -0,0 +1 @@
+file(CONFIGURE CONTENT "")
diff --git a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
index 502298518..008ce6751 100644
--- a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
@@ -9,6 +9,8 @@ run_cmake(DirOutput)
run_cmake(NewLineStyle-NoArg)
run_cmake(NewLineStyle-ValidArg)
run_cmake(NewLineStyle-WrongArg)
+run_cmake(NoArgOutput)
+run_cmake(NoArgContent)
run_cmake(SubDir)
run_cmake(AtOnly)
run_cmake(EscapeQuotes)
diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
index e823b25dd..708e6bec4 100644
--- a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
+++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at EmptyCondition1.cmake:2 \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ Error after keyword "CONDITION":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-check.cmake b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
new file mode 100644
index 000000000..5c9b80361
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-INPUT.txt" input)
+if(NOT input MATCHES "INPUT file")
+ string(APPEND RunCMake_TEST_FAILED "INPUT incorrectly overridden by CONTENT")
+endif()
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-CONTENT.txt" content)
+if(NOT content MATCHES "CONTENT argument")
+ string(APPEND RunCMake_TEST_FAILED "CONTENT incorrectly overridden by INPUT")
+endif()
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-input.txt b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
new file mode 100644
index 000000000..73f162ba9
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
@@ -0,0 +1 @@
+INPUT file
diff --git a/Tests/RunCMake/File_Generate/InputAndContent.cmake b/Tests/RunCMake/File_Generate/InputAndContent.cmake
new file mode 100644
index 000000000..9c3977ab3
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent.cmake
@@ -0,0 +1,10 @@
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-INPUT.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+ CONTENT "CONTENT argument"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-CONTENT.txt"
+ CONTENT "CONTENT argument"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
index bc71f2f59..b1b7f80a1 100644
--- a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ Error after keyword "NEWLINE_STYLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index be3bf04dd..5a670ae4f 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -17,6 +17,7 @@ run_cmake(EmptyCondition2)
run_cmake(BadCondition)
run_cmake(DebugEvaluate)
run_cmake(GenerateSource)
+run_cmake(InputAndContent)
run_cmake(OutputNameMatchesSources)
run_cmake(OutputNameMatchesObjects)
run_cmake(OutputNameMatchesOtherSources)
diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
index f479dcf4f..661ae3f30 100644
--- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
@@ -24,6 +24,27 @@ endif()
# We need a real pkg-config to run the test for get_variable.
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
+ string(FIND "${CMAKE_CURRENT_BINARY_DIR}" " " IS_SPACES_IN_PATH)
+ if(IS_SPACES_IN_PATH GREATER -1)
+ string(REPLACE " " "\\ " ESCAPED_ROOT "${CMAKE_CURRENT_BINARY_DIR}")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_spaces.pc" "
+libdir=${ESCAPED_ROOT}
+Name: test_spaces.pc
+Version: 0.0
+Description: test spaces
+Libs: -L\${libdir}
+")
+ set(PKG_CONFIG_PATH_SAVED "$ENV{PKG_CONFIG_PATH}")
+ set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}")
+ execute_process(COMMAND "${PKG_CONFIG_EXECUTABLE}" --libs test_spaces
+ ERROR_QUIET COMMAND_ERROR_IS_FATAL ANY
+ OUTPUT_VARIABLE test_spaces_LIBS)
+ set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH_SAVED}")
+ string(STRIP "${test_spaces_LIBS}" test_spaces_LIBS_STRIPPED)
+ if(NOT "${test_spaces_LIBS_STRIPPED}" STREQUAL "-L${ESCAPED_ROOT}")
+ set(PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH TRUE)
+ endif()
+ endif()
run_cmake(FindPkgConfig_GET_VARIABLE)
run_cmake(FindPkgConfig_GET_VARIABLE_PREFIX_PATH)
run_cmake(FindPkgConfig_GET_VARIABLE_PKGCONFIG_PATH)
@@ -32,5 +53,7 @@ if (PKG_CONFIG_FOUND)
run_cmake(FindPkgConfig_VERSION_OPERATORS)
run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME)
run_cmake(FindPkgConfig_empty_target)
- run_cmake(FindPkgConfig_LIBRARY_PATH)
+ if(NOT PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH)
+ run_cmake(FindPkgConfig_LIBRARY_PATH)
+ endif()
endif ()
diff --git a/Tests/RunCMake/Framework/FrameworkConsumption.cmake b/Tests/RunCMake/Framework/FrameworkConsumption.cmake
index 466316665..58b70a31c 100644
--- a/Tests/RunCMake/Framework/FrameworkConsumption.cmake
+++ b/Tests/RunCMake/Framework/FrameworkConsumption.cmake
@@ -13,3 +13,21 @@ set_target_properties(Gui PROPERTIES
add_executable(app main.c)
target_link_libraries(app PRIVATE Gui)
+
+
+# Same test but with generation done in custom directories
+add_library(Gui2 SHARED Gui.c "${input_header}")
+set_target_properties(Gui2 PROPERTIES
+ PUBLIC_HEADER "${input_header}"
+ FRAMEWORK TRUE
+ LIBRARY_OUTPUT_DIRECTORY lib
+)
+
+add_executable(app2 main2.c)
+set_target_properties(Gui2 PROPERTIES
+ PUBLIC_HEADER "${input_header}"
+ FRAMEWORK TRUE
+ RUNTIME_OUTPUT_DIRECTORY bin
+)
+
+target_link_libraries(app2 PRIVATE Gui2)
diff --git a/Tests/RunCMake/Framework/main2.c b/Tests/RunCMake/Framework/main2.c
new file mode 100644
index 000000000..11f4e4d53
--- /dev/null
+++ b/Tests/RunCMake/Framework/main2.c
@@ -0,0 +1,9 @@
+
+#include <Gui2/Gui.h>
+
+int main()
+{
+ foo();
+
+ return 0;
+}
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt
new file mode 100644
index 000000000..fb61d4b8f
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error in CMakeLists.txt:
+ MSVC_DEBUG_INFORMATION_FORMAT value 'BogusValue' not known for this (C|CXX)
+ compiler.
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake
new file mode 100644
index 000000000..165ea3821
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0141 NEW)
+include(CMP0141-common.cmake)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake
new file mode 100644
index 000000000..82754a95c
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake
@@ -0,0 +1,4 @@
+include(CMP0141-common.cmake)
+
+# Setting this policy after enable_language command has no effect.
+cmake_policy(SET CMP0141 NEW)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake
new file mode 100644
index 000000000..7bbe586d7
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0141 OLD)
+include(CMP0141-common.cmake)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake
new file mode 100644
index 000000000..912112adc
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0141-common.cmake)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake
new file mode 100644
index 000000000..8e43a25c5
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake
@@ -0,0 +1,31 @@
+enable_language(CXX)
+
+cmake_policy(GET CMP0141 cmp0141)
+if(cmp0141 STREQUAL "NEW")
+ if(NOT CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
+ message(SEND_ERROR "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT not set under NEW behavior")
+ endif()
+else()
+ if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
+ message(SEND_ERROR "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT is set under OLD behavior")
+ endif()
+endif()
+
+if(cmp0141 STREQUAL "NEW")
+ if(CMAKE_CXX_FLAGS_DEBUG MATCHES "[/-]Zi( |$)")
+ message(SEND_ERROR "CMAKE_CXX_FLAGS_DEBUG has -Zi flags under NEW behavior.")
+ endif()
+ if(CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "[/-]Zi( |$)")
+ message(SEND_ERROR "CMAKE_CXX_FLAGS_RELWITHDEBINFO has -Zi flags under NEW behavior.")
+ endif()
+else()
+ if(NOT (CMAKE_CXX_FLAGS_DEBUG MATCHES "[/-]Zi( |$)"))
+ message(SEND_ERROR "CMAKE_CXX_FLAGS_DEBUG does not have -Zi flags under OLD behavior.")
+ endif()
+ if(NOT (CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "[/-]Zi( |$)"))
+ message(SEND_ERROR "CMAKE_CXX_FLAGS_RELWITHDEBINFO does not have -Zi flags under OLD behavior.")
+ endif()
+endif()
+
+set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT BogusValue)
+add_library(foo empty.cxx)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt
new file mode 100644
index 000000000..aba10165b
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.24)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake
new file mode 100644
index 000000000..f678acf94
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake
@@ -0,0 +1,6 @@
+include(RunCMake)
+
+run_cmake(CMP0141-WARN)
+run_cmake(CMP0141-OLD)
+run_cmake(CMP0141-NEW)
+run_cmake(CMP0141-NoEffect)
diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx b/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx
diff --git a/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake b/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake
new file mode 100644
index 000000000..059b91741
--- /dev/null
+++ b/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake
@@ -0,0 +1,17 @@
+enable_language(CXX)
+
+set(QtX Qt${with_qt_version})
+
+find_package(${QtX} REQUIRED COMPONENTS Core)
+
+set(CMAKE_AUTOMOC ON)
+
+add_library(simple_lib SHARED simple_lib.cpp)
+add_executable(app_with_qt app.cpp app_qt.cpp)
+
+target_link_libraries(app_with_qt PRIVATE simple_lib ${QtX}::Core)
+
+set_source_files_properties(app.cpp app_qt.cpp
+ PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
+
+target_precompile_headers(app_with_qt PRIVATE [["QObject"]])
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 0825666a0..b94466ce8 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -42,6 +42,15 @@ function(run_Intl)
endfunction()
run_Intl()
+if(WIN32)
+ if(RunCMake_MAKE_PROGRAM)
+ set(maybe_MAKE_PROGRAM "-DRunCMake_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
+ endif()
+ run_cmake_script(ShowIncludes-54936 -DshowIncludes=${showIncludes} ${maybe_MAKE_PROGRAM})
+ run_cmake_script(ShowIncludes-65001 -DshowIncludes=${showIncludes} ${maybe_MAKE_PROGRAM})
+ unset(maybe_MAKE_PROGRAM)
+endif()
+
function(run_NoWorkToDo)
run_cmake(NoWorkToDo)
set(RunCMake_TEST_NO_CLEAN 1)
@@ -366,6 +375,22 @@ function(run_QtAutoMocDeps)
run_ninja("${RunCMake_TEST_BINARY_DIR}")
endif()
endfunction()
+
+function(run_QtAutoMocSkipPch)
+ set(QtX Qt${CMake_TEST_Qt_version})
+ if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocSkipPch-build)
+ run_cmake_with_options(QtAutoMocSkipPch
+ "-Dwith_qt_version=${CMake_TEST_Qt_version}"
+ "-D${QtX}_DIR=${${QtX}_DIR}"
+ "-D${QtX}Core_DIR=${${QtX}Core_DIR}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
+ )
+ # Build the project.
+ run_ninja("${RunCMake_TEST_BINARY_DIR}")
+ endif()
+endfunction()
if(CMake_TEST_Qt_version)
run_QtAutoMocDeps()
+ run_QtAutoMocSkipPch()
endif()
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-54936-check.cmake b/Tests/RunCMake/Ninja/ShowIncludes-54936-check.cmake
new file mode 100644
index 000000000..40bb68f6d
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-54936-check.cmake
@@ -0,0 +1,3 @@
+# 'cl /showIncludes' prefix with 'VSLANG=2052' and 'chcp 54936'.
+string(ASCII 215 162 210 226 58 32 176 252 186 172 206 196 188 254 58 expect)
+include(${CMAKE_CURRENT_LIST_DIR}/ShowIncludes-check.cmake)
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-54936-stdout.txt b/Tests/RunCMake/Ninja/ShowIncludes-54936-stdout.txt
new file mode 100644
index 000000000..42a2f35ac
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-54936-stdout.txt
@@ -0,0 +1 @@
+-- showIncludes='注意: 包含文件:'
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-54936.cmake b/Tests/RunCMake/Ninja/ShowIncludes-54936.cmake
new file mode 100644
index 000000000..07b4192c7
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-54936.cmake
@@ -0,0 +1,2 @@
+set(CODEPAGE 54936)
+include(${CMAKE_CURRENT_LIST_DIR}/ShowIncludes.cmake)
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-65001-check.cmake b/Tests/RunCMake/Ninja/ShowIncludes-65001-check.cmake
new file mode 100644
index 000000000..c73b7344b
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-65001-check.cmake
@@ -0,0 +1,3 @@
+# 'cl /showIncludes' prefix with 'VSLANG=2052' and 'chcp 65001'.
+string(ASCII 230 179 168 230 132 143 58 32 229 140 133 229 144 171 230 150 135 228 187 182 58 expect)
+include(${CMAKE_CURRENT_LIST_DIR}/ShowIncludes-check.cmake)
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-65001-stdout.txt b/Tests/RunCMake/Ninja/ShowIncludes-65001-stdout.txt
new file mode 100644
index 000000000..42a2f35ac
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-65001-stdout.txt
@@ -0,0 +1 @@
+-- showIncludes='注意: 包含文件:'
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-65001.cmake b/Tests/RunCMake/Ninja/ShowIncludes-65001.cmake
new file mode 100644
index 000000000..0eebd6165
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-65001.cmake
@@ -0,0 +1,2 @@
+set(CODEPAGE 65001)
+include(${CMAKE_CURRENT_LIST_DIR}/ShowIncludes.cmake)
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-check.cmake b/Tests/RunCMake/Ninja/ShowIncludes-check.cmake
new file mode 100644
index 000000000..304a7f689
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-check.cmake
@@ -0,0 +1,17 @@
+set(rules_ninja "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/rules.ninja")
+if(NOT EXISTS "${rules_ninja}")
+ set(RunCMake_TEST_FAILED "Generator output file is missing:\n ${rules_ninja}")
+ return()
+endif()
+
+file(READ "${rules_ninja}" rules_ninja)
+if(rules_ninja MATCHES "msvc_deps_prefix = ([^\r\n]*)\n")
+ set(actual "${CMAKE_MATCH_1}")
+endif()
+
+if(NOT actual STREQUAL expect)
+ string(HEX "${actual}" actual_hex)
+ string(HEX "${expect}" expect_hex)
+ set(RunCMake_TEST_FAILED "Expected byte sequence\n '${expect}' (${expect_hex})\nbut got\n '${actual}' (${actual_hex})")
+ return()
+endif()
diff --git a/Tests/RunCMake/Ninja/ShowIncludes-cmake.cmake b/Tests/RunCMake/Ninja/ShowIncludes-cmake.cmake
new file mode 100644
index 000000000..672a89f38
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes-cmake.cmake
@@ -0,0 +1,7 @@
+# Set the console code page.
+execute_process(COMMAND cmd /c chcp "${CODEPAGE}")
+
+if(RunCMake_MAKE_PROGRAM)
+ set(maybe_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
+endif()
+execute_process(COMMAND "${CMAKE_COMMAND}" . -G Ninja ${maybe_MAKE_PROGRAM})
diff --git a/Tests/RunCMake/Ninja/ShowIncludes.cmake b/Tests/RunCMake/Ninja/ShowIncludes.cmake
new file mode 100644
index 000000000..b9f89fe24
--- /dev/null
+++ b/Tests/RunCMake/Ninja/ShowIncludes.cmake
@@ -0,0 +1,22 @@
+# Create a project to do showIncludes prefix detection.
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeLists.txt" "
+cmake_minimum_required(VERSION 3.25)
+project(ShowIncludes NONE)
+include(CMakeDetermineCompilerId)
+set(CMAKE_dummy_COMPILER \"${showIncludes}\")
+CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(dummy \"\")
+set(CMAKE_CL_SHOWINCLUDES_PREFIX \"\${CMAKE_dummy_CL_SHOWINCLUDES_PREFIX}\")
+file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/showIncludes.txt\" \"\${CMAKE_CL_SHOWINCLUDES_PREFIX}\")
+")
+
+if(RunCMake_MAKE_PROGRAM)
+ set(maybe_MAKE_PROGRAM "-DRunCMake_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
+endif()
+
+# Run cmake in a new Window to isolate its console code page.
+execute_process(COMMAND cmd /c start /min /wait ""
+ ${CMAKE_COMMAND} -DCODEPAGE=${CODEPAGE} ${maybe_MAKE_PROGRAM} -P ${CMAKE_CURRENT_LIST_DIR}/ShowIncludes-cmake.cmake)
+
+# Print our internal UTF-8 representation of the showIncludes prefix.
+file(READ "${CMAKE_CURRENT_BINARY_DIR}/showIncludes.txt" showIncludes_txt)
+message(STATUS "showIncludes='${showIncludes_txt}'")
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
new file mode 100644
index 000000000..a1ae6ac99
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
@@ -0,0 +1,28 @@
+set(expected_compile_commands
+[==[^\[
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Debug[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+},
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Release[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+}
+]$]==])
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" actual_compile_commands)
+if(NOT actual_compile_commands MATCHES "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " expected_compile_commands_formatted "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " actual_compile_commands_formatted "${actual_compile_commands}")
+ string(APPEND RunCMake_TEST_FAILED "Expected compile_commands.json to match:\n ${expected_compile_commands_formatted}\nActual compile_commands.json:\n ${actual_compile_commands_formatted}\n")
+endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
new file mode 100644
index 000000000..fc44d5ad8
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main.c)
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index 738bc6c5d..c040e8f1e 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -453,6 +453,11 @@ run_cmake_command(NoUnusedVariables ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}
"-DCMAKE_DEFAULT_BUILD_TYPE=Debug"
"-DCMAKE_DEFAULT_CONFIGS=all"
)
+unset(RunCMake_TEST_BINARY_DIR)
+
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_CROSS_CONFIGS=all;-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
+run_cmake(CompileCommands)
+unset(RunCMake_TEST_OPTIONS)
# CudaSimple uses separable compilation, which is currently only supported on NVCC.
if(CMake_TEST_CUDA)
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
index 1410eae78..df4ef1fcb 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
@@ -155,6 +155,7 @@ foreach(t ${targets})
cmake_parse_implicit_link_info("${input}" implicit_libs idirs implicit_fwks log
"${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}"
+ LANGUAGE ${lang}
COMPUTE_IMPLICIT_OBJECTS implicit_objs)
set(library_arch)
diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake
index 59ee14b9f..18b09c1c1 100644
--- a/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(DisabledPch C)
+enable_language(C)
add_library(foo foo.c)
target_include_directories(foo PUBLIC include)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchDebugGenex.cmake b/Tests/RunCMake/PrecompileHeaders/PchDebugGenex.cmake
index 854689fd8..039a546b6 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchDebugGenex.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchDebugGenex.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchDebugGenex C)
+enable_language(C)
add_library(foo foo.c)
target_include_directories(foo PUBLIC include)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
index a4554103d..eef189ae6 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchIncludedAllLanguages C CXX)
+enable_language(C)
+enable_language(CXX)
if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake
index dd582aca8..6c5e89d86 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchIncludedOneLanguage.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 3.16)
-project(PchIncludedAllLanguages C CXX)
+enable_language(C)
+enable_language(CXX)
if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake
index aab20d8f5..c031660f5 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchInterface C)
+enable_language(C)
add_library(foo foo.c)
target_include_directories(foo PUBLIC include)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake
index b4fdb712a..ad8a32818 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.16)
-project(PchLibObjLibExe CXX)
+enable_language(CXX)
foreach(i 1 2 3)
file(WRITE ${CMAKE_BINARY_DIR}/empty${i}.cpp "void nothing${i}() {}\n")
diff --git a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake
index bb18a6423..d8abf8e09 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchMultilanguage C CXX)
+enable_language(C)
+enable_language(CXX)
add_executable(foobar
foo.c
diff --git a/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake
index 3e27620f9..988c4c69f 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake
@@ -1,6 +1,5 @@
-cmake_minimum_required(VERSION 3.15)
-
-project(PchPrologueEpilogue)
+enable_language(C)
+enable_language(CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake
new file mode 100644
index 000000000..41c7d22f3
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0141 NEW)
+set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "")
+string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -Zi")
+include(PchReuseFrom-common.cmake)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake
new file mode 100644
index 000000000..daf7a3879
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0141 NEW)
+include(PchReuseFrom-common.cmake)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake
new file mode 100644
index 000000000..9586887fd
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0141 OLD)
+include(PchReuseFrom-common.cmake)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-common.cmake
index f8fba441a..8d5e94507 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-common.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchReuseFrom C)
+enable_language(C)
if(CMAKE_C_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake
index ba504a3ef..510877ff0 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake
@@ -1,6 +1,5 @@
-cmake_minimum_required(VERSION 3.18)
-
-project(PchReuseFromObjLib)
+enable_language(C)
+enable_language(CXX)
set(CMAKE_PCH_WARN_INVALID OFF)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
index e306d8e9c..14703e336 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchReuseFromPrefixed C)
+enable_language(C)
if(CMAKE_C_COMPILE_OPTIONS_USE_PCH)
add_definitions(-DHAVE_PCH_SUPPORT)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
index fff74dcd6..fefb4eeeb 100644
--- a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
-project(PchReuseFromSubdir C)
+enable_language(C)
add_library(empty empty.c)
target_precompile_headers(empty PUBLIC
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index fd41e2f8e..b163369a2 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -15,7 +15,11 @@ run_test(PchInterface)
run_cmake(PchPrologueEpilogue)
run_test(SkipPrecompileHeaders)
run_test(CXXnotC)
-run_test(PchReuseFrom)
+run_test(PchReuseFrom-CMP0141-OLD)
+run_test(PchReuseFrom-CMP0141-NEW)
+if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
+ run_test(PchReuseFrom-CMP0141-NEW-empty)
+endif()
run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir)
run_cmake(PchMultilanguage)
diff --git a/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake b/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake
index 49efbfbab..7405e658c 100644
--- a/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake
@@ -1,6 +1,5 @@
-cmake_minimum_required(VERSION 3.15)
-
-project(SkipPrecompileHeaders)
+enable_language(C)
+enable_language(CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 1c92ca0fd..ba9cc3b96 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -1,8 +1,10 @@
-foreach(arg
+foreach(
+ arg
+ IN ITEMS
RunCMake_GENERATOR
RunCMake_SOURCE_DIR
RunCMake_BINARY_DIR
- )
+ )
if(NOT DEFINED ${arg})
message(FATAL_ERROR "${arg} not given!")
endif()
@@ -31,7 +33,7 @@ function(run_cmake test)
set(platform_name msys)
endif()
- foreach(o out err)
+ foreach(o IN ITEMS out err)
if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file})
file(READ ${top_src}/${RunCMake-std${o}-file} expect_std${o})
string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}")
@@ -162,6 +164,7 @@ function(run_cmake test)
"|Your license to use PGI[^\n]*expired"
"|Please obtain a new version at"
"|contact PGI Sales at"
+ "|icp?c: remark #10441: The Intel\\(R\\) C\\+\\+ Compiler Classic \\(ICC\\) is deprecated"
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
"|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
@@ -176,7 +179,7 @@ function(run_cmake test)
"|[^\n]*Bullseye Testing Technology"
")[^\n]*\n)+"
)
- foreach(o out err)
+ foreach(o IN ITEMS out err)
string(REGEX REPLACE "\r\n" "\n" actual_std${o} "${actual_std${o}}")
string(REGEX REPLACE "${ignore_line_regex}" "\\1" actual_std${o} "${actual_std${o}}")
string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}")
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 97c339450..0d8e4c94f 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -36,6 +36,7 @@
\* CMP0113
\* CMP0119
\* CMP0131
+ \* CMP0142
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake b/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake
new file mode 100644
index 000000000..46af974c7
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake
@@ -0,0 +1,46 @@
+macro(DebugInformationFormat_check tgt Debug_expect Release_expect MinSizeRel_expect RelWithDebInfo_expect)
+ set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj")
+ if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.")
+ return()
+ endif()
+
+ set(Debug_actual "")
+ set(Release_actual "")
+ set(MinSizeRel_actual "")
+ set(RelWithDebInfo_actual "")
+
+ file(STRINGS "${vcProjectFile}" lines)
+ foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<ItemDefinitionGroup Condition=\"'\\$\\(Configuration\\)\\|\\$\\(Platform\\)'=='([^<>]+)\\|[A-Za-z0-9_]+'\">")
+ set(Configuration "${CMAKE_MATCH_1}")
+ endif()
+ if(line MATCHES "^ *<DebugInformationFormat>([^<>]+)</DebugInformationFormat>")
+ set(${Configuration}_actual "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+
+ if (NOT "${Debug_actual}" STREQUAL "${Debug_expect}")
+ set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj Debug Configuration has DebugInformationFormat '${Debug_actual}', not '${Debug_expect}'.")
+ endif()
+ if (NOT "${Release_actual}" STREQUAL "${Release_expect}")
+ set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj Release Configuration has DebugInformationFormat '${Release_actual}', not '${Release_expect}'.")
+ endif()
+ if (NOT "${MinSizeRel_actual}" STREQUAL "${MinSizeRel_expect}")
+ set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj MinSizeRel Configuration has DebugInformationFormat '${MinSizeRel_actual}', not '${MinSizeRel_expect}'.")
+ endif()
+ if (NOT "${RelWithDebInfo_actual}" STREQUAL "${RelWithDebInfo_expect}")
+ set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj RelWithDebInfo Configuration has DebugInformationFormat '${RelWithDebInfo_actual}', not '${RelWithDebInfo_expect}'.")
+ endif()
+endmacro()
+
+DebugInformationFormat_check(default-C ProgramDatabase "" "" ProgramDatabase)
+DebugInformationFormat_check(default-CXX ProgramDatabase "" "" ProgramDatabase)
+DebugInformationFormat_check(empty-C "" "" "" "")
+DebugInformationFormat_check(empty-CXX "" "" "" "")
+DebugInformationFormat_check(Embedded-C OldStyle OldStyle OldStyle OldStyle)
+DebugInformationFormat_check(Embedded-CXX OldStyle OldStyle OldStyle OldStyle)
+DebugInformationFormat_check(ProgramDatabase-C ProgramDatabase ProgramDatabase ProgramDatabase ProgramDatabase)
+DebugInformationFormat_check(ProgramDatabase-CXX ProgramDatabase ProgramDatabase ProgramDatabase ProgramDatabase)
+DebugInformationFormat_check(EditAndContinue-C EditAndContinue EditAndContinue EditAndContinue EditAndContinue)
+DebugInformationFormat_check(EditAndContinue-CXX EditAndContinue EditAndContinue EditAndContinue EditAndContinue)
diff --git a/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake b/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake
new file mode 100644
index 000000000..f6701664c
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake
@@ -0,0 +1,24 @@
+set(CMAKE_CONFIGURATION_TYPES Debug Release MinSizeRel RelWithDebInfo)
+cmake_policy(SET CMP0141 NEW)
+enable_language(C)
+enable_language(CXX)
+
+add_library(default-C empty.c)
+add_library(default-CXX empty.cxx)
+
+set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "")
+add_library(empty-C empty.c)
+add_library(empty-CXX empty.cxx)
+
+set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded")
+add_library(Embedded-C empty.c)
+add_library(Embedded-CXX empty.cxx)
+
+set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
+add_library(ProgramDatabase-C empty.c)
+add_library(ProgramDatabase-CXX empty.cxx)
+
+add_library(EditAndContinue-C empty.c)
+set_property(TARGET EditAndContinue-C PROPERTY MSVC_DEBUG_INFORMATION_FORMAT "EditAndContinue")
+add_library(EditAndContinue-CXX empty.cxx)
+set_property(TARGET EditAndContinue-CXX PROPERTY MSVC_DEBUG_INFORMATION_FORMAT "EditAndContinue")
diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
index bcdc10105..1701a36aa 100644
--- a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
+++ b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
@@ -5,6 +5,7 @@ if(NOT EXISTS "${vcProjectFile}")
endif()
set(found_iface_h 0)
+set(found_int_dir 0)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*iface\\.h")
@@ -19,7 +20,15 @@ foreach(line IN LISTS lines)
endif()
set(found_iface_h 1)
endif()
+ if(line MATCHES "^ *<IntDir [^<>]+>[^<>]+</IntDir>")
+ set(found_int_dir 1)
+ endif()
endforeach()
if(NOT found_iface_h)
set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${vcProjectFile}")
+ return()
+endif()
+if(NOT found_int_dir)
+ set(RunCMake_TEST_FAILED "No references to IntDir in\n ${vcProjectFile}")
+ return()
endif()
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index e540b9fc4..f027e94ed 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -88,3 +88,4 @@ run_cmake(VsDotnetStartupObject)
run_cmake(VsDotnetTargetFramework)
run_cmake(VsDotnetTargetFrameworkVersion)
run_cmake(VsNoCompileBatching)
+run_cmake(DebugInformationFormat)
diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake b/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake
index 100f48287..4d5508da0 100644
--- a/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake
+++ b/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake
@@ -9,7 +9,7 @@ function(check_file target filename)
if(filename MATCHES "^(.*)(\\.[a-z]+)$")
set(header_filename "${CMAKE_MATCH_1}")
endif()
- set(expected_contents "#include <${header_filename}>\n")
+ set(expected_contents "#include <${header_filename}> // IWYU pragma: associated\n")
file(READ "${full_filename}" actual_contents)
if(NOT actual_contents STREQUAL expected_contents)
diff --git a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
index 9c9074ed7..22e2bb3b5 100644
--- a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ include(RunCMake)
run_cmake(VsDotnetSdkCustomCommandsTarget)
run_cmake(VsDotnetSdkCustomCommandsSource)
run_cmake(VsDotnetSdkStartupObject)
+run_cmake(VsDotnetSdkDefines)
run_cmake(DotnetSdkVariables)
function(run_VsDotnetSdk)
diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdk.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdk.cmake
index c585f5ece..bd914f821 100644
--- a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdk.cmake
+++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdk.cmake
@@ -6,16 +6,22 @@ project (DotNetSdk CSharp)
set(CMAKE_DOTNET_TARGET_FRAMEWORK net472)
set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk")
+if(CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
+ set(VS_RT_IDENTIFIER arm64)
+else()
+ set(VS_RT_IDENTIFIER win10-x64)
+endif()
+
add_library(dotNetSdkLib1 SHARED lib1.cs)
set_target_properties(dotNetSdkLib1
PROPERTIES
- VS_GLOBAL_RuntimeIdentifier win10-x64)
+ VS_GLOBAL_RuntimeIdentifier ${VS_RT_IDENTIFIER})
add_executable(DotNetSdk csharponly.cs)
target_link_libraries(DotNetSdk dotNetSdkLib1)
set_target_properties(DotNetSdk
PROPERTIES
- VS_GLOBAL_RuntimeIdentifier win10-x64
+ VS_GLOBAL_RuntimeIdentifier ${VS_RT_IDENTIFIER}
VS_DOTNET_REFERENCE_SomeDll
${PROJECT_SOURCE_DIR}/SomeDll.dll)
diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake
new file mode 100644
index 000000000..eaeba2439
--- /dev/null
+++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake
@@ -0,0 +1,64 @@
+#
+# Check C# VS project for required elements.
+#
+set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj")
+if(NOT EXISTS "${csProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.")
+ return()
+endif()
+
+
+set(inDebug FALSE)
+set(inRelease FALSE)
+set(debugOK FALSE)
+set(releaseOK FALSE)
+
+
+file(STRINGS "${csProjectFile}" lines)
+foreach(line IN LISTS lines)
+ #message(STATUS ${line})
+ if(line MATCHES "^ *<PropertyGroup .*Debug.*")
+ set(inDebug TRUE)
+ elseif(line MATCHES "^ *<PropertyGroup .*Release.*")
+ set(inRelease TRUE)
+ elseif(line MATCHES "^ *</PropertyGroup> *$")
+ set(inRelease FALSE)
+ set(inDebug FALSE)
+ elseif(inDebug AND
+ (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND
+ (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$") AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$")) AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$"))
+ )
+ set(debugOK TRUE)
+ elseif(inRelease AND
+ (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND
+ (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$") AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$")) AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$"))
+ )
+ set(releaseOK TRUE)
+ endif()
+endforeach()
+
+function(print_csprojfile)
+ file(STRINGS "${csProjectFile}" lines)
+ foreach(line IN LISTS lines)
+ message(STATUS ${line})
+ endforeach()
+endfunction()
+
+
+if(NOT debugOK)
+ message(STATUS "Failed to set Debug configuration defines correctly.")
+ set(RunCMake_TEST_FAILED "Failed to set Debug configuration defines correctly.")
+ print_csprojfile()
+ return()
+endif()
+
+if(NOT releaseOK)
+ message(STATUS "Failed to set Release configuration defines correctly.")
+ set(RunCMake_TEST_FAILED "Failed to set Release configuration defines correctly.")
+ print_csprojfile()
+ return()
+endif()
diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake
new file mode 100644
index 000000000..d89f19b8f
--- /dev/null
+++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake
@@ -0,0 +1,19 @@
+enable_language(CSharp)
+if(NOT CMAKE_CSharp_COMPILER)
+ return()
+endif()
+
+set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk")
+set(CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION "net5.0")
+
+add_executable(foo csharponly.cs lib1.cs)
+
+# Issue 23376
+target_compile_definitions(
+ foo
+ PUBLIC
+ MY_FOO_DEFINE
+ "MY_BAR_ASSIGNMENT=bar"
+ $<$<CONFIG:Debug>:DEFINE_ONLY_FOR_DEBUG>
+ $<$<CONFIG:Release>:DEFINE_ONLY_FOR_RELEASE>
+)
diff --git a/Tests/RunCMake/XcodeProject/Clean-build-check.cmake b/Tests/RunCMake/XcodeProject/Clean-build-check.cmake
new file mode 100644
index 000000000..605881a52
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/Clean-build-check.cmake
@@ -0,0 +1,5 @@
+set(pattern "${RunCMake_TEST_BINARY_DIR}/build/empty.build/Debug/Objects-normal/*/empty.o")
+file(GLOB objs "${pattern}")
+if(NOT objs)
+ set(RunCMake_TEST_FAILED "Expected object does not exist:\n ${pattern}")
+endif()
diff --git a/Tests/RunCMake/XcodeProject/Clean-clean-check.cmake b/Tests/RunCMake/XcodeProject/Clean-clean-check.cmake
new file mode 100644
index 000000000..76ea8a14f
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/Clean-clean-check.cmake
@@ -0,0 +1,5 @@
+set(pattern "${RunCMake_TEST_BINARY_DIR}/build/empty.build/Debug/Objects-normal/*/empty.o")
+file(GLOB objs "${pattern}")
+if(objs)
+ set(RunCMake_TEST_FAILED "Object file(s) not cleaned:\n ${objs}")
+endif()
diff --git a/Tests/RunCMake/XcodeProject/Clean.cmake b/Tests/RunCMake/XcodeProject/Clean.cmake
new file mode 100644
index 000000000..1ab7e10c1
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/Clean.cmake
@@ -0,0 +1,2 @@
+enable_language(C)
+add_subdirectory(Clean)
diff --git a/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt b/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt
new file mode 100644
index 000000000..59e62cb94
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(empty empty.c)
diff --git a/Tests/RunCMake/XcodeProject/Clean/empty.c b/Tests/RunCMake/XcodeProject/Clean/empty.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/Clean/empty.c
diff --git a/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake b/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake
new file mode 100644
index 000000000..4a3bf561b
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+
+set_property(GLOBAL PROPERTY XCODE_EMIT_EFFECTIVE_PLATFORM_NAME OFF)
+
+set(CMAKE_MACOSX_BUNDLE true)
+
+add_library(library STATIC foo.cpp)
+
+add_executable(main main.cpp)
+target_link_libraries(main library)
+
+install(TARGETS library ARCHIVE DESTINATION lib)
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 128a9dcab..573d5f719 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -1,5 +1,14 @@
include(RunCMake)
+function(RunClean)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Clean-build)
+ run_cmake(Clean -DCMAKE_CONFIGURATION_TYPES=Debug)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(Clean-build xcodebuild)
+ run_cmake_command(Clean-clean xcodebuild clean)
+endfunction()
+RunClean()
+
run_cmake(ExplicitCMakeLists)
run_cmake(ImplicitCMakeLists)
run_cmake(InterfaceLibSources)
@@ -346,6 +355,7 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 6)
endif()
if(NOT XCODE_VERSION VERSION_LESS 5)
+ # XcodeMultiplatform
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeMultiplatform-build)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_OPTIONS "${IOS_DEPLOYMENT_TARGET}")
@@ -365,6 +375,23 @@ if(NOT XCODE_VERSION VERSION_LESS 5)
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
unset(RunCMake_TEST_OPTIONS)
+
+ # EffectivePlatformNameOFF
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EffectivePlatformNameOFF-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME=iOS" "-DCMAKE_OSX_SYSROOT=iphonesimulator")
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake(EffectivePlatformNameOFF)
+
+ run_cmake_command(EffectivePlatformNameOFF-iphonesimulator-build ${CMAKE_COMMAND} --build .)
+ run_cmake_command(EffectivePlatformNameOFF-iphonesimulator-install ${CMAKE_COMMAND} --build . --target install -- DESTDIR=${RunCMake_TEST_BINARY_DIR}/_install_iphonesimulator)
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+ unset(RunCMake_TEST_OPTIONS)
endif()
if(XCODE_VERSION VERSION_GREATER_EQUAL 8)
diff --git a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake
index 71b7d8fae..bec8790f8 100644
--- a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake
+++ b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake
@@ -12,6 +12,8 @@ set(found_target_library_FRAMEWORK_SEARCH_PATHS 0)
set(found_inherited_FRAMEWORK_SEARCH_PATHS 0)
set(found_project_LIBRARY_SEARCH_PATHS 0)
set(found_target_library_LIBRARY_SEARCH_PATHS 0)
+set(found_target_cmp0142old_LIBRARY_SEARCH_PATHS 0)
+set(found_target_cmp0142new_LIBRARY_SEARCH_PATHS 0)
set(found_inherited_LIBRARY_SEARCH_PATHS 0)
file(STRINGS "${xcProjectFile}" lines)
foreach(line IN LISTS lines)
@@ -42,6 +44,12 @@ foreach(line IN LISTS lines)
if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib/\$\(CONFIGURATION\)\$\(EFFECTIVE_PLATFORM_NAME\)(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]])
set(found_target_library_LIBRARY_SEARCH_PATHS 1)
endif()
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142OLD/\$\(CONFIGURATION\)\$\(EFFECTIVE_PLATFORM_NAME\)(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142OLD(\\")?","\$\(inherited\)"\);]])
+ set(found_target_cmp0142old_LIBRARY_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142NEW(\\")?","\$\(inherited\)"\);]])
+ set(found_target_cmp0142new_LIBRARY_SEARCH_PATHS 1)
+ endif()
if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("\$\(inherited\)"\);]])
set(found_inherited_LIBRARY_SEARCH_PATHS 1)
endif()
@@ -68,6 +76,12 @@ endif()
if(NOT found_target_library_LIBRARY_SEARCH_PATHS)
string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'library' in\n ${xcProjectFile}\n")
endif()
+if(NOT found_target_cmp0142old_LIBRARY_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'cmp0142old' in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_target_cmp0142new_LIBRARY_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'cmp0142new' in\n ${xcProjectFile}\n")
+endif()
if(found_inherited_LIBRARY_SEARCH_PATHS)
string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value in\n ${xcProjectFile}\n")
endif()
diff --git a/Tests/RunCMake/XcodeProject/SearchPaths.cmake b/Tests/RunCMake/XcodeProject/SearchPaths.cmake
index ef977092b..b4697720d 100644
--- a/Tests/RunCMake/XcodeProject/SearchPaths.cmake
+++ b/Tests/RunCMake/XcodeProject/SearchPaths.cmake
@@ -3,6 +3,8 @@ enable_language(C)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142OLD")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142NEW")
set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
set(CMAKE_XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
@@ -19,3 +21,11 @@ target_include_directories(include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSe
add_executable(library main.c)
target_link_libraries(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework")
target_link_directories(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib")
+
+cmake_policy(SET CMP0142 OLD)
+add_executable(cmp0142old main.c)
+target_link_directories(cmp0142old PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142OLD")
+
+cmake_policy(SET CMP0142 NEW)
+add_executable(cmp0142new main.c)
+target_link_directories(cmp0142new PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142NEW")
diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
index be44ecdbb..6bad52738 100644
--- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
+++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
@@ -29,6 +29,8 @@ check_property("UNDEFINED_BEHAVIOUR_SANITIZER" "enableUBSanitizer")
check_property("UNDEFINED_BEHAVIOUR_SANITIZER_STOP" "stopOnEveryUBSanitizerIssue")
check_property("DISABLE_MAIN_THREAD_CHECKER" "disableMainThreadChecker")
check_property("MAIN_THREAD_CHECKER_STOP" "stopOnEveryMainThreadCheckerIssue")
+check_property("DISABLE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION" "enableGPUValidationMode")
+check_property("ENABLE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION" "enableGPUShaderValidationMode")
check_property("MALLOC_SCRIBBLE" "MallocScribble")
check_property("MALLOC_GUARD_EDGES" "MallocGuardEdges")
@@ -43,6 +45,8 @@ check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED" "enableGPUFrameCaptureMo
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL" "enableGPUFrameCaptureMode=\"1\"")
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE" "enableGPUFrameCaptureMode=\"3\"")
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE" "enableGPUFrameCaptureMode=\"1\"")
+check_property("LAUNCH_MODE_AUTO" "launchStyle=\"0\"")
+check_property("LAUNCH_MODE_WAIT" "launchStyle=\"1\"")
check_property("EXECUTABLE" "myExecutable")
check_property("ARGUMENTS" [=["--foo"]=])
diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
index 126a9fc9d..267e3797a 100644
--- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
+++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
@@ -32,12 +32,16 @@ function(create_scheme_for_property scheme property value)
set_target_properties(${scheme} PROPERTIES XCODE_SCHEME_${property} "${value}")
endfunction()
+create_scheme_for_property(DISABLE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION ENABLE_GPU_API_VALIDATION OFF)
+create_scheme_for_property(ENABLE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION ENABLE_GPU_SHADER_VALIDATION ON)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_1 ENABLE_GPU_FRAME_CAPTURE_MODE 1)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_3 ENABLE_GPU_FRAME_CAPTURE_MODE 3)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED ENABLE_GPU_FRAME_CAPTURE_MODE Disabled)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL ENABLE_GPU_FRAME_CAPTURE_MODE Metal)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE DISAbled)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE METal)
+create_scheme_for_property(LAUNCH_MODE_AUTO LAUNCH_MODE AUTO)
+create_scheme_for_property(LAUNCH_MODE_WAIT LAUNCH_MODE WAIT)
create_scheme_for_property(EXECUTABLE EXECUTABLE myExecutable)
create_scheme_for_property(ARGUMENTS ARGUMENTS "--foo;--bar=baz")
create_scheme_for_property(ENVIRONMENT ENVIRONMENT "FOO=foo;BAR=bar")
diff --git a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
index 951e03c8f..ddf45af7f 100644
--- a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
@@ -3,6 +3,7 @@ include(RunCMake)
run_cmake(DoesNotExist)
run_cmake(Missing)
run_cmake(Function)
+run_cmake(System)
macro(run_cmake_install case)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
diff --git a/Tests/RunCMake/add_subdirectory/System.cmake b/Tests/RunCMake/add_subdirectory/System.cmake
new file mode 100644
index 000000000..45d7d9aa0
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+
+add_subdirectory(System SYSTEM)
+
+function(check_target_system target expected_value)
+ get_target_property(var ${target} SYSTEM)
+ if ((var AND NOT expected_value) OR (NOT var AND expected_value))
+ message(SEND_ERROR "\
+The 'SYSTEM' property of ${target} should be ${expected_value}, \
+but got ${var}")
+ endif()
+endfunction()
+
+check_target_system(foo OFF)
+check_target_system(bar ON)
+check_target_system(zot ON)
+check_target_system(subsub1foo OFF)
+check_target_system(subsub1bar ON)
+check_target_system(subsub1zot ON)
+check_target_system(subsub2foo OFF)
+check_target_system(subsub2bar ON)
+check_target_system(subsub2zot ON)
diff --git a/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt
new file mode 100644
index 000000000..ef74e8003
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt
@@ -0,0 +1,11 @@
+project(SystemSub NONE)
+
+add_subdirectory(SubSub1 SYSTEM)
+add_subdirectory(SubSub2)
+
+add_library(bar STATIC bar.cpp)
+
+add_library(foo STATIC foo.cpp)
+set_target_properties(foo PROPERTIES SYSTEM OFF)
+
+add_executable(zot zot.cpp)
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt
new file mode 100644
index 000000000..291339b8e
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(subsub1bar STATIC bar.cpp)
+
+add_library(subsub1foo STATIC foo.cpp)
+set_target_properties(subsub1foo PROPERTIES SYSTEM OFF)
+
+add_executable(subsub1zot zot.cpp)
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt
new file mode 100644
index 000000000..5755742d7
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(subsub2bar STATIC bar.cpp)
+
+add_library(subsub2foo STATIC foo.cpp)
+set_target_properties(subsub2foo PROPERTIES SYSTEM OFF)
+
+add_executable(subsub2zot zot.cpp)
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/bar.cpp b/Tests/RunCMake/add_subdirectory/System/bar.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/bar.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/foo.cpp b/Tests/RunCMake/add_subdirectory/System/foo.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/foo.cpp
diff --git a/Tests/RunCMake/add_subdirectory/System/zot.cpp b/Tests/RunCMake/add_subdirectory/System/zot.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/System/zot.cpp
diff --git a/Tests/RunCMake/block/CMakeLists.txt b/Tests/RunCMake/block/CMakeLists.txt
new file mode 100644
index 000000000..45cd10ecc
--- /dev/null
+++ b/Tests/RunCMake/block/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.3...3.25)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/block/EndAlone-result.txt b/Tests/RunCMake/block/EndAlone-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/EndAlone-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/EndAlone-stderr.txt b/Tests/RunCMake/block/EndAlone-stderr.txt
new file mode 100644
index 000000000..a588dd7be
--- /dev/null
+++ b/Tests/RunCMake/block/EndAlone-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at EndAlone.cmake:[0-9]+ \(endblock\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/EndAlone.cmake b/Tests/RunCMake/block/EndAlone.cmake
new file mode 100644
index 000000000..0c428a90b
--- /dev/null
+++ b/Tests/RunCMake/block/EndAlone.cmake
@@ -0,0 +1 @@
+endblock()
diff --git a/Tests/RunCMake/block/EndAloneWithArgument-result.txt b/Tests/RunCMake/block/EndAloneWithArgument-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/EndAloneWithArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt b/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt
new file mode 100644
index 000000000..c3d25a315
--- /dev/null
+++ b/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at EndAloneWithArgument.cmake:[0-9]+ \(endblock\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/EndAloneWithArgument.cmake b/Tests/RunCMake/block/EndAloneWithArgument.cmake
new file mode 100644
index 000000000..05df5b0d6
--- /dev/null
+++ b/Tests/RunCMake/block/EndAloneWithArgument.cmake
@@ -0,0 +1 @@
+endblock(WRONG_ARG)
diff --git a/Tests/RunCMake/block/EndMissing-result.txt b/Tests/RunCMake/block/EndMissing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/EndMissing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/EndMissing-stderr.txt b/Tests/RunCMake/block/EndMissing-stderr.txt
new file mode 100644
index 000000000..b9739a5be
--- /dev/null
+++ b/Tests/RunCMake/block/EndMissing-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at EndMissing.cmake:[0-9]+ \(block\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/EndMissing.cmake b/Tests/RunCMake/block/EndMissing.cmake
new file mode 100644
index 000000000..335b64eee
--- /dev/null
+++ b/Tests/RunCMake/block/EndMissing.cmake
@@ -0,0 +1 @@
+block()
diff --git a/Tests/RunCMake/block/EndWithArgument-stderr.txt b/Tests/RunCMake/block/EndWithArgument-stderr.txt
new file mode 100644
index 000000000..758645385
--- /dev/null
+++ b/Tests/RunCMake/block/EndWithArgument-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) in EndWithArgument.cmake:
+ A logical block closing on the line
+
+ .+/Tests/RunCMake/block/EndWithArgument.cmake:[0-9]+ \(endblock\)
+
+ has unexpected arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/block/EndWithArgument.cmake b/Tests/RunCMake/block/EndWithArgument.cmake
new file mode 100644
index 000000000..0641c9a10
--- /dev/null
+++ b/Tests/RunCMake/block/EndWithArgument.cmake
@@ -0,0 +1,2 @@
+block()
+endblock(END_ARG)
diff --git a/Tests/RunCMake/block/InvalidArgument-result.txt b/Tests/RunCMake/block/InvalidArgument-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidArgument-stderr.txt b/Tests/RunCMake/block/InvalidArgument-stderr.txt
new file mode 100644
index 000000000..bee604b89
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidArgument-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidArgument.cmake:[0-9]+ \(block\):
+ block PROPAGATE cannot be specified without a new scope for VARIABLES
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidArgument.cmake b/Tests/RunCMake/block/InvalidArgument.cmake
new file mode 100644
index 000000000..5269cd077
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidArgument.cmake
@@ -0,0 +1,2 @@
+block(SCOPE_FOR POLICIES PROPAGATE VAR1)
+endblock()
diff --git a/Tests/RunCMake/block/InvalidNesting1-result.txt b/Tests/RunCMake/block/InvalidNesting1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting1-stderr.txt b/Tests/RunCMake/block/InvalidNesting1-stderr.txt
new file mode 100644
index 000000000..6dfe0e10d
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting1-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting1.cmake:[0-9]+ \(else\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting1.cmake b/Tests/RunCMake/block/InvalidNesting1.cmake
new file mode 100644
index 000000000..27b794463
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting1.cmake
@@ -0,0 +1,6 @@
+
+if (TRUE)
+ block()
+else()
+ endblock()
+endif()
diff --git a/Tests/RunCMake/block/InvalidNesting2-result.txt b/Tests/RunCMake/block/InvalidNesting2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting2-stderr.txt b/Tests/RunCMake/block/InvalidNesting2-stderr.txt
new file mode 100644
index 000000000..71325b6a9
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting2-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting2.cmake:[0-9]+ \(endblock\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting2.cmake b/Tests/RunCMake/block/InvalidNesting2.cmake
new file mode 100644
index 000000000..ae94cdcb3
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting2.cmake
@@ -0,0 +1,6 @@
+
+block()
+if (TRUE)
+elseif(FALSE)
+endblock()
+endif()
diff --git a/Tests/RunCMake/block/InvalidNesting3-result.txt b/Tests/RunCMake/block/InvalidNesting3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting3-stderr.txt b/Tests/RunCMake/block/InvalidNesting3-stderr.txt
new file mode 100644
index 000000000..344a931e6
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting3-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting3.cmake:[0-9]+ \(endwhile\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting3.cmake b/Tests/RunCMake/block/InvalidNesting3.cmake
new file mode 100644
index 000000000..f692d244d
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting3.cmake
@@ -0,0 +1,5 @@
+
+while(TRUE)
+block()
+endwhile()
+endblock()
diff --git a/Tests/RunCMake/block/InvalidNesting4-result.txt b/Tests/RunCMake/block/InvalidNesting4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting4-stderr.txt b/Tests/RunCMake/block/InvalidNesting4-stderr.txt
new file mode 100644
index 000000000..44d636462
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting4-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting4.cmake:[0-9]+ \(endblock\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting4.cmake b/Tests/RunCMake/block/InvalidNesting4.cmake
new file mode 100644
index 000000000..6e8e0ae6b
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting4.cmake
@@ -0,0 +1,5 @@
+
+block()
+foreach(item IN ITEMS A B)
+endblock()
+endforeach()
diff --git a/Tests/RunCMake/block/InvalidNesting5-result.txt b/Tests/RunCMake/block/InvalidNesting5-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting5-stderr.txt b/Tests/RunCMake/block/InvalidNesting5-stderr.txt
new file mode 100644
index 000000000..976d2e1ea
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting5-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting5.cmake:[0-9]+ \(endfunction\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting5.cmake b/Tests/RunCMake/block/InvalidNesting5.cmake
new file mode 100644
index 000000000..0479e8da9
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting5.cmake
@@ -0,0 +1,5 @@
+
+function(FUNC)
+ block()
+endfunction()
+endblock()
diff --git a/Tests/RunCMake/block/InvalidNesting6-result.txt b/Tests/RunCMake/block/InvalidNesting6-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/InvalidNesting6-stderr.txt b/Tests/RunCMake/block/InvalidNesting6-stderr.txt
new file mode 100644
index 000000000..2d67b16b8
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting6-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at InvalidNesting6.cmake:[0-9]+ \(endblock\):
+ Flow control statements are not properly nested.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/InvalidNesting6.cmake b/Tests/RunCMake/block/InvalidNesting6.cmake
new file mode 100644
index 000000000..a1cb359bb
--- /dev/null
+++ b/Tests/RunCMake/block/InvalidNesting6.cmake
@@ -0,0 +1,5 @@
+
+ block()
+macro(FUNC)
+endblock()
+endmacro()
diff --git a/Tests/RunCMake/block/MissingArgument-result.txt b/Tests/RunCMake/block/MissingArgument-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/MissingArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/MissingArgument-stderr.txt b/Tests/RunCMake/block/MissingArgument-stderr.txt
new file mode 100644
index 000000000..d3e63cadf
--- /dev/null
+++ b/Tests/RunCMake/block/MissingArgument-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at MissingArgument.cmake:[0-9]+ \(block\):
+ Error after keyword "SCOPE_FOR":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/MissingArgument.cmake b/Tests/RunCMake/block/MissingArgument.cmake
new file mode 100644
index 000000000..60188871a
--- /dev/null
+++ b/Tests/RunCMake/block/MissingArgument.cmake
@@ -0,0 +1,2 @@
+block(SCOPE_FOR)
+endblock()
diff --git a/Tests/RunCMake/block/RunCMakeTest.cmake b/Tests/RunCMake/block/RunCMakeTest.cmake
new file mode 100644
index 000000000..4260e76ad
--- /dev/null
+++ b/Tests/RunCMake/block/RunCMakeTest.cmake
@@ -0,0 +1,22 @@
+include(RunCMake)
+
+run_cmake(WrongArgument)
+run_cmake(InvalidArgument)
+run_cmake(MissingArgument)
+run_cmake(WrongScope)
+run_cmake(EndMissing)
+run_cmake(EndWithArgument)
+run_cmake(EndAlone)
+run_cmake(EndAloneWithArgument)
+
+run_cmake(InvalidNesting1)
+run_cmake(InvalidNesting2)
+run_cmake(InvalidNesting3)
+run_cmake(InvalidNesting4)
+run_cmake(InvalidNesting5)
+run_cmake(InvalidNesting6)
+
+run_cmake(Scope)
+run_cmake(Scope-VARIABLES)
+run_cmake(Scope-POLICIES)
+run_cmake(Workflows)
diff --git a/Tests/RunCMake/block/Scope-POLICIES.cmake b/Tests/RunCMake/block/Scope-POLICIES.cmake
new file mode 100644
index 000000000..9536a9975
--- /dev/null
+++ b/Tests/RunCMake/block/Scope-POLICIES.cmake
@@ -0,0 +1,40 @@
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
+cmake_policy(SET CMP0139 NEW)
+
+# create a block with a new scope for policies
+block(SCOPE_FOR POLICIES)
+ set(VAR1 "INNER1")
+ unset(VAR2)
+ set(VAR3 "INNER3")
+ add_subdirectory(Scope)
+
+ cmake_policy(SET CMP0139 OLD)
+endblock()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "INNER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(DEFINED VAR2)
+ message(SEND_ERROR "block/endblock: VAR2 is unexpectedly defined: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "SUBDIR1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
+
+cmake_policy(GET CMP0139 CMP0139_STATUS)
+if(NOT CMP0139_STATUS STREQUAL "NEW")
+ message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}")
+endif()
diff --git a/Tests/RunCMake/block/Scope-VARIABLES.cmake b/Tests/RunCMake/block/Scope-VARIABLES.cmake
new file mode 100644
index 000000000..ac8da140c
--- /dev/null
+++ b/Tests/RunCMake/block/Scope-VARIABLES.cmake
@@ -0,0 +1,62 @@
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+set(VAR3 "OUTER3")
+set(VAR4 "OUTER4")
+set(VAR5 "OUTER5")
+
+set(VAR6 "CACHE6" CACHE STRING "")
+set(VAR6 "OUTER6")
+
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
+cmake_policy(SET CMP0139 NEW)
+
+# create a block with a new scope for variables
+block(SCOPE_FOR VARIABLES PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7 VARSUB2)
+ set(VAR1 "INNER1")
+ set(VAR2 "INNER2" PARENT_SCOPE)
+ set(VAR3 "INNER3")
+ unset(VAR4)
+ unset(VAR6)
+ set(VAR7 "INNER7")
+ add_subdirectory(Scope)
+
+ cmake_policy(SET CMP0139 OLD)
+endblock()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2")
+ message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
+if(DEFINED VAR4)
+ message(SEND_ERROR "block/endblock: VAR4 is unexpectedly defined: ${VAR4}")
+endif()
+if(NOT DEFINED VAR5 OR NOT VAR5 STREQUAL "OUTER5")
+ message(SEND_ERROR "block/endblock: VAR5 has unexpected value: ${VAR5}")
+endif()
+unset(VAR6 CACHE)
+if (DEFINED VAR6)
+ message(SEND_ERROR "block/endblock: VAR6 is unexpectedly defined: ${VAR6}")
+endif()
+if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7")
+ message(SEND_ERROR "block/endblock: VAR7 has unexpected value: ${VAR7}")
+endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "OUTERSUB1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
+
+cmake_policy(GET CMP0139 CMP0139_STATUS)
+if(NOT CMP0139_STATUS STREQUAL "OLD")
+ message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}")
+endif()
diff --git a/Tests/RunCMake/block/Scope.cmake b/Tests/RunCMake/block/Scope.cmake
new file mode 100644
index 000000000..ef43df604
--- /dev/null
+++ b/Tests/RunCMake/block/Scope.cmake
@@ -0,0 +1,62 @@
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+set(VAR3 "OUTER3")
+set(VAR4 "OUTER4")
+set(VAR5 "OUTER5")
+
+set(VAR6 "CACHE6" CACHE STRING "")
+set(VAR6 "OUTER6")
+
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
+cmake_policy(SET CMP0139 NEW)
+
+# create a block with a new scope for variables and policies
+block(PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7 VARSUB2)
+ set(VAR1 "INNER1")
+ set(VAR2 "INNER2" PARENT_SCOPE)
+ set(VAR3 "INNER3")
+ unset(VAR4)
+ unset(VAR6)
+ set(VAR7 "INNER7")
+ add_subdirectory(Scope)
+
+ cmake_policy(SET CMP0139 OLD)
+endblock()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2")
+ message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
+if(DEFINED VAR4)
+ message(SEND_ERROR "block/endblock: VAR4 is unexpectedly defined: ${VAR4}")
+endif()
+if(NOT DEFINED VAR5 OR NOT VAR5 STREQUAL "OUTER5")
+ message(SEND_ERROR "block/endblock: VAR5 has unexpected value: ${VAR5}")
+endif()
+unset(VAR6 CACHE)
+if (DEFINED VAR6)
+ message(SEND_ERROR "block/endblock: VAR6 is unexpectedly defined: ${VAR6}")
+endif()
+if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7")
+ message(SEND_ERROR "block/endblock: VAR6 has unexpected value: ${VAR7}")
+endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "OUTERSUB1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
+
+cmake_policy(GET CMP0139 CMP0139_STATUS)
+if(NOT CMP0139_STATUS STREQUAL "NEW")
+ message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}")
+endif()
diff --git a/Tests/RunCMake/block/Scope/CMakeLists.txt b/Tests/RunCMake/block/Scope/CMakeLists.txt
new file mode 100644
index 000000000..afd79e301
--- /dev/null
+++ b/Tests/RunCMake/block/Scope/CMakeLists.txt
@@ -0,0 +1,2 @@
+set(VARSUB1 "SUBDIR1" PARENT_SCOPE)
+set(VARSUB2 "SUBDIR2" PARENT_SCOPE)
diff --git a/Tests/RunCMake/block/Workflows.cmake b/Tests/RunCMake/block/Workflows.cmake
new file mode 100644
index 000000000..cbf032eb4
--- /dev/null
+++ b/Tests/RunCMake/block/Workflows.cmake
@@ -0,0 +1,78 @@
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+set(VAR3 "OUTER3")
+
+while (TRUE)
+ # create a block with a new scope for variables
+ block(SCOPE_FOR VARIABLES PROPAGATE VAR3)
+ set(VAR2 "INNER2" PARENT_SCOPE)
+ set(VAR3 "INNER3")
+ break()
+ endblock()
+endwhile()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2")
+ message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
+
+
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+set(VAR3 "OUTER3")
+
+function (OUTER)
+ # create a block with a new scope for variables
+ block(SCOPE_FOR VARIABLES PROPAGATE VAR3)
+ set(VAR2 "INNER2" PARENT_SCOPE)
+ set(VAR3 "INNER3")
+ return()
+ endblock()
+ set(VAR1 "INNER1" PARENT_SCOPE)
+endfunction()
+outer()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OUTER2")
+ message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "OUTER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
+
+
+
+set(VAR1 "OUTER1")
+set(VAR2 "OUTER2")
+set(VAR3 "OUTER3")
+
+foreach (id IN ITEMS 1 2 3)
+ # create a block with a new scope for variables
+ block(SCOPE_FOR VARIABLES PROPAGATE VAR${id})
+ set(VAR${id} "INNER${id}")
+ continue()
+ set(VAR${id} "BAD${id}")
+ endblock()
+endforeach()
+
+# check final values for variables
+if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "INNER1")
+ message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}")
+endif()
+if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2")
+ message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}")
+endif()
+if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
+ message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
+endif()
diff --git a/Tests/RunCMake/block/WrongArgument-result.txt b/Tests/RunCMake/block/WrongArgument-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/WrongArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/WrongArgument-stderr.txt b/Tests/RunCMake/block/WrongArgument-stderr.txt
new file mode 100644
index 000000000..56faea70c
--- /dev/null
+++ b/Tests/RunCMake/block/WrongArgument-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at WrongArgument.cmake:[0-9]+ \(block\):
+ block called with unsupported argument "WRONG_ARG"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/WrongArgument.cmake b/Tests/RunCMake/block/WrongArgument.cmake
new file mode 100644
index 000000000..e46086656
--- /dev/null
+++ b/Tests/RunCMake/block/WrongArgument.cmake
@@ -0,0 +1,2 @@
+block(WRONG_ARG)
+endblock()
diff --git a/Tests/RunCMake/block/WrongScope-result.txt b/Tests/RunCMake/block/WrongScope-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/block/WrongScope-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/block/WrongScope-stderr.txt b/Tests/RunCMake/block/WrongScope-stderr.txt
new file mode 100644
index 000000000..dd2a1efbe
--- /dev/null
+++ b/Tests/RunCMake/block/WrongScope-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at WrongScope.cmake:[0-9]+ \(block\):
+ block SCOPE_FOR unsupported scope "WRONG_SCOPE"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/block/WrongScope.cmake b/Tests/RunCMake/block/WrongScope.cmake
new file mode 100644
index 000000000..97a6783a6
--- /dev/null
+++ b/Tests/RunCMake/block/WrongScope.cmake
@@ -0,0 +1,2 @@
+block(SCOPE_FOR WRONG_SCOPE)
+endblock()
diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
index 6a430f181..ea1566d9a 100644
--- a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
+++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
@@ -1,5 +1,7 @@
CMake Error at Registry_BadQuery2.cmake:[0-9]+ \(cmake_host_system_information\):
- cmake_host_system_information missing expected value for argument\(s\)
- "VALUE".
+ Error after keyword "VALUE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
index 5eda4ffb7..f8c96d8ff 100644
--- a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
+++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
@@ -1,5 +1,7 @@
CMake Error at Registry_BadView1.cmake:[0-9]+ \(cmake_host_system_information\):
- cmake_host_system_information missing expected value for argument\(s\)
- "VIEW".
+ Error after keyword "VIEW":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
index 6480b2e0c..38ce10bbd 100644
--- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
@@ -8,6 +8,7 @@ foreach(command IN ITEMS
"if" "elseif" "else" "endif"
"while" "endwhile"
"foreach" "endforeach"
+ "block" "endblock"
)
message(STATUS "Running call_invalid_command for ${command}...")
run_cmake_with_options(call_invalid_command -Dcommand=${command})
@@ -42,6 +43,7 @@ foreach(command IN ITEMS
"if" "elseif" "else" "endif"
"while" "endwhile"
"foreach" "endforeach"
+ "block" "endblock"
"return"
)
message(STATUS "Running defer_call_invalid_command for ${command}...")
@@ -82,3 +84,61 @@ run_cmake(defer_get_call_id_var)
run_cmake(defer_missing_arg)
run_cmake(defer_missing_call)
run_cmake(defer_unknown_option)
+
+# Default log level
+run_cmake_command(
+ get_message_log_level_none
+ ${CMAKE_COMMAND}
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from cache
+run_cmake_command(
+ get_message_log_level_cache
+ ${CMAKE_COMMAND}
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from regular variable
+run_cmake_command(
+ get_message_log_level_var
+ ${CMAKE_COMMAND}
+ -DNEW_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line
+run_cmake_command(
+ get_message_log_level_cli
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line, it has higher priority over a cache variable
+run_cmake_command(
+ get_message_log_level_cli_and_cache
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line, it has higher priority over a regular variable
+run_cmake_command(
+ get_message_log_level_cli_and_var
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -DNEW_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from variable, it has higher priority over a cache variable
+run_cmake_command(
+ get_message_log_level_var_and_cache
+ ${CMAKE_COMMAND}
+ -DNEW_LOG_LEVEL=DEBUG
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level.cmake b/Tests/RunCMake/cmake_language/get_message_log_level.cmake
new file mode 100644
index 000000000..1740c1f70
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level.cmake
@@ -0,0 +1,5 @@
+if(NEW_LOG_LEVEL)
+ set(CMAKE_MESSAGE_LOG_LEVEL "${NEW_LOG_LEVEL}")
+endif()
+cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
+message(STATUS "log level is: ${log_level}")
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt
new file mode 100644
index 000000000..cf1cd7b1c
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: TRACE
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt
new file mode 100644
index 000000000..4d6e1ebe0
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt
new file mode 100644
index 000000000..4d6e1ebe0
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt
new file mode 100644
index 000000000..4d6e1ebe0
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt
new file mode 100644
index 000000000..92ffd3497
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt
@@ -0,0 +1 @@
+log level is: STATUS
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt
new file mode 100644
index 000000000..cf1cd7b1c
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt
@@ -0,0 +1 @@
+log level is: TRACE
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt
new file mode 100644
index 000000000..4d6e1ebe0
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt
new file mode 100644
index 000000000..ad7d134f0
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
+ Error after keyword "BASE_DIRECTORY":
+
+ missing required value
diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt
new file mode 100644
index 000000000..f1b52cc4a
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .+/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ empty string not allowed
diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
index e1d6592cf..63289ef85 100644
--- a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
+++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
@@ -1,2 +1,4 @@
CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
- cmake_path OUTPUT_VARIABLE requires an argument.
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
diff --git a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
index 991f46b09..1742b0662 100644
--- a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
@@ -74,6 +74,14 @@ foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
endforeach()
+## BASE_DIRECTORY without argument
+set (RunCMake-stderr-file "BASE_DIRECTORY-no-arg-stderr.txt")
+
+foreach (command IN ITEMS RELATIVE_PATH ABSOLUTE_PATH)
+ run_cmake_command (${command}-OUTPUT_VARIABLE-no-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path BASE_DIRECTORY" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
+endforeach()
+
+
## Invalid output variable
set (RunCMake-stderr-file "invalid-output-var-stderr.txt")
@@ -106,6 +114,9 @@ foreach (command IN ITEMS NATIVE_PATH
run_cmake_command (${command}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path ${extra_args}" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
+# OUTPUT_VARIABLE empty name
+set (RunCMake-stderr-file "OUTPUT_VARIABLE-empty-stderr.txt")
+
foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
RELATIVE_PATH ABSOLUTE_PATH)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt
new file mode 100644
index 000000000..a7eae0583
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt
@@ -0,0 +1 @@
+CTEST_TEST_VAR=set-via-ENVIRONMENT-property
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake
new file mode 100644
index 000000000..51e7f2aab
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake
@@ -0,0 +1,9 @@
+include(CTest)
+
+add_test(NAME cmake_environment COMMAND "${CMAKE_COMMAND}" -E environment)
+set_tests_properties(
+ cmake_environment
+ PROPERTIES
+ ENVIRONMENT "CTEST_TEST_VAR=set-via-ENVIRONMENT-property"
+ ENVIRONMENT_MODIFICATION "CTEST_TEST_VAR=set:set-via-ENVIRONMENT_MODIFICATION;CTEST_TEST_VAR=reset:"
+)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt
new file mode 100644
index 000000000..beaf133ec
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt
@@ -0,0 +1 @@
+CTEST_TEST_VAR=set-via-system-environment
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake
new file mode 100644
index 000000000..23268aac3
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake
@@ -0,0 +1,9 @@
+include(CTest)
+
+add_test(NAME cmake_environment COMMAND "${CMAKE_COMMAND}" -E environment)
+set_tests_properties(
+ cmake_environment
+ PROPERTIES
+ # ENVIRONMENT "CTEST_TEST_VAR=set-via-ENVIRONMENT-property"
+ ENVIRONMENT_MODIFICATION "CTEST_TEST_VAR=set:set-via-ENVIRONMENT_MODIFICATION;CTEST_TEST_VAR=reset:"
+)
diff --git a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake
index 3447779f3..365c9e833 100644
--- a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake
@@ -10,3 +10,7 @@ set(RunCTest_VERBOSE_FLAG "-VV")
run_ctest(ENVIRONMENT_MODIFICATION-invalid-op)
run_ctest(ENVIRONMENT_MODIFICATION-no-colon)
run_ctest(ENVIRONMENT_MODIFICATION-no-equals)
+
+set(ENV{CTEST_TEST_VAR} set-via-system-environment)
+run_ctest(ENVIRONMENT_MODIFICATION-reset-to-prop)
+run_ctest(ENVIRONMENT_MODIFICATION-reset-to-system)
diff --git a/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake
index adc7a1a36..850f72cc0 100644
--- a/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake
+++ b/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake
@@ -277,3 +277,12 @@ file(APPEND "${LOG_FILE}"
=========
========= RACECHECK SUMMARY: 12 hazards displayed (0 errors, 12 warnings)
")
+
+# false-positives
+file(APPEND "${LOG_FILE}"
+"========= COMPUTE-SANITIZER
+========= Error: Target application terminated before first instrumented API call
+========= Tracking kernels launched by child processes requires the --target-processes all option.
+========= Error: No attachable process found. compute-sanitizer timed-out.
+========= Default timeout can be adjusted with --launch-timeout. Awaiting target completion.
+")
diff --git a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
index e27f1e6d2..62cad521f 100644
--- a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
+++ b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
@@ -1,2 +1,4 @@
CMake Error at .*EchoCommand.cmake:.*\(execute_process\):
- execute_process called with no value for COMMAND_ECHO.
+ Error after keyword "COMMAND_ECHO":
+
+ missing required value
diff --git a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
index 1a695790f..7f85654c6 100644
--- a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
+++ b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
@@ -1,4 +1,7 @@
^CMake Error at EncodingMissing.cmake:[0-9]+ \(execute_process\):
- execute_process called with no value for ENCODING.
+ Error after keyword "ENCODING":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt
deleted file mode 100644
index b22387bbd..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at CHMOD-all-perms\.cmake:[0-9]+ \(file\):
- file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS
- from the invocation
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake
deleted file mode 100644
index b49583d5c..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ
- FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt
deleted file mode 100644
index 8d09e3510..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error at CHMOD-invalid-path\.cmake:[0-9]+ \(file\):
- file does not exist:
-
- .*/chmod-tests/I_dont_exist
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake
deleted file mode 100644
index 36915c15b..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/I_dont_exist PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt
deleted file mode 100644
index 84ba2a299..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-invalid-perms\.cmake:[0-9]+ \(file\):
- file INVALID_PERMISSION is an invalid permission specifier
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake
deleted file mode 100644
index 22cab0b14..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS INVALID_PERMISSION)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt
deleted file mode 100644
index 2c248f8bf..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-no-keyword\.cmake:[0-9]+ \(file\):
- file No permissions given
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake
deleted file mode 100644
index 8b6210651..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt
deleted file mode 100644
index a18609f2c..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-no-perms\.cmake:[0-9]+ \(file\):
- file No permissions given
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake
deleted file mode 100644
index 9fbd3599d..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake
deleted file mode 100644
index 87e3e5766..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake
deleted file mode 100644
index d9226b835..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt
deleted file mode 100644
index 1c87a593f..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error at CHMOD-write-only\.cmake:[0-9]+ \(file\):
- file failed to open for reading \(Permission denied\):
-
- .*/chmod-tests/a
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake
deleted file mode 100644
index 1289efc10..000000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a "CONTENT")
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_WRITE)
-file(READ ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a content)
diff --git a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
index 18deb8951..e6b11694d 100644
--- a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
@@ -1,12 +1,14 @@
include(RunCMake)
-run_cmake(CHMOD-no-perms)
-run_cmake(CHMOD-no-keyword)
-run_cmake(CHMOD-all-perms)
-run_cmake(CHMOD-invalid-perms)
-run_cmake(CHMOD-invalid-path)
-run_cmake(CHMOD-ok)
-run_cmake(CHMOD-override)
+run_cmake_script(no-perms)
+run_cmake_script(missing-perms)
+run_cmake_script(missing-file-perms)
+run_cmake_script(missing-dir-perms)
+run_cmake_script(all-perms)
+run_cmake_script(invalid-perms)
+run_cmake_script(invalid-path)
+run_cmake_script(ok)
+run_cmake_script(override)
if(UNIX)
execute_process(COMMAND id -u $ENV{USER}
@@ -15,5 +17,5 @@ if(UNIX)
endif()
if(NOT WIN32 AND NOT MSYS AND NOT "${uid}" STREQUAL "0")
- run_cmake(CHMOD-write-only)
+ run_cmake_script(write-only)
endif()
diff --git a/Tests/RunCMake/file-CHMOD/all-perms-result.txt b/Tests/RunCMake/file-CHMOD/all-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/all-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt
new file mode 100644
index 000000000..6932a1f0b
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at [^
+]*/all-perms\.cmake:[0-9]+ \(file\):
+ file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS
+ from the invocation$
diff --git a/Tests/RunCMake/file-CHMOD/all-perms.cmake b/Tests/RunCMake/file-CHMOD/all-perms.cmake
new file mode 100644
index 000000000..5ff81b85f
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/all-perms.cmake
@@ -0,0 +1,3 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ
+ FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/invalid-path-result.txt b/Tests/RunCMake/file-CHMOD/invalid-path-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-path-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt
new file mode 100644
index 000000000..eb5fb3163
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/invalid-path\.cmake:[0-9]+ \(file\):
+ file does not exist:
+
+ [^
+]*/Tests/RunCMake/file-CHMOD/invalid-path-build/I_dont_exist$
diff --git a/Tests/RunCMake/file-CHMOD/invalid-path.cmake b/Tests/RunCMake/file-CHMOD/invalid-path.cmake
new file mode 100644
index 000000000..e8b0313c4
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-path.cmake
@@ -0,0 +1 @@
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/I_dont_exist PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt
new file mode 100644
index 000000000..daab22e4e
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/invalid-perms\.cmake:[0-9]+ \(file\):
+ file INVALID_PERMISSION is an invalid permission specifier$
diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake
new file mode 100644
index 000000000..42129b9df
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS INVALID_PERMISSION)
diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt
new file mode 100644
index 000000000..c05bb2dd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-dir-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "DIRECTORY_PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake
new file mode 100644
index 000000000..9d0fdade8
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt
new file mode 100644
index 000000000..c3f4f0f17
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-file-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "FILE_PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake
new file mode 100644
index 000000000..bcf35aa19
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ FILE_PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/missing-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt
new file mode 100644
index 000000000..1508b130c
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-perms.cmake
new file mode 100644
index 000000000..da9f182f6
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a FILE_PERMISSIONS OWNER_READ PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/no-perms-result.txt b/Tests/RunCMake/file-CHMOD/no-perms-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/no-perms-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt
new file mode 100644
index 000000000..4c5a13983
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/no-perms\.cmake:[0-9]+ \(file\):
+ file No permissions given$
diff --git a/Tests/RunCMake/file-CHMOD/no-perms.cmake b/Tests/RunCMake/file-CHMOD/no-perms.cmake
new file mode 100644
index 000000000..602cfc20f
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/no-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a)
diff --git a/Tests/RunCMake/file-CHMOD/ok.cmake b/Tests/RunCMake/file-CHMOD/ok.cmake
new file mode 100644
index 000000000..7c74d2776
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/ok.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/override.cmake b/Tests/RunCMake/file-CHMOD/override.cmake
new file mode 100644
index 000000000..67e5a23ca
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/override.cmake
@@ -0,0 +1,3 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
diff --git a/Tests/RunCMake/file-CHMOD/write-only-result.txt b/Tests/RunCMake/file-CHMOD/write-only-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/write-only-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file-CHMOD/write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt
new file mode 100644
index 000000000..169a09266
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/write-only\.cmake:[0-9]+ \(file\):
+ file failed to open for reading \(Permission denied\):
+
+ [^
+]*/Tests/RunCMake/file-CHMOD/write-only-build/a$
diff --git a/Tests/RunCMake/file-CHMOD/write-only.cmake b/Tests/RunCMake/file-CHMOD/write-only.cmake
new file mode 100644
index 000000000..aa9d8038b
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/write-only.cmake
@@ -0,0 +1,3 @@
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/a "CONTENT")
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_WRITE)
+file(READ ${CMAKE_CURRENT_BINARY_DIR}/a content)
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
index c6ad3d090..39f307d2e 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
@@ -13,11 +13,21 @@ Call Stack \(most recent call first\):
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Error at badargs2\.cmake:[0-9]+ \(file\):
- file Keywords missing values:
+ Error after keyword "BUNDLE_EXECUTABLE":
+
+ missing required value
+
+ Error after keyword "CONFLICTING_DEPENDENCIES_PREFIX":
+
+ missing required value
+
+ Error after keyword "RESOLVED_DEPENDENCIES_VAR":
+
+ missing required value
+
+ Error after keyword "UNRESOLVED_DEPENDENCIES_VAR":
+
+ missing required value
- RESOLVED_DEPENDENCIES_VAR
- UNRESOLVED_DEPENDENCIES_VAR
- CONFLICTING_DEPENDENCIES_PREFIX
- BUNDLE_EXECUTABLE
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
index 7c58aeb4a..54a3e5a72 100644
--- a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
+++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
@@ -1,2 +1,7 @@
-CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\):
- file BASE_DIRECTORY requires a value
+^CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\):
+ Error after keyword "BASE_DIRECTORY":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index aff4735f4..db889568e 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -47,6 +47,7 @@ run_cmake(GLOB_RECURSE)
run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
run_cmake(SIZE)
run_cmake(SIZE-error-does-not-exist)
+run_cmake(TIMESTAMP)
run_cmake(REMOVE-empty)
diff --git a/Tests/RunCMake/file/TIMESTAMP-stdout.txt b/Tests/RunCMake/file/TIMESTAMP-stdout.txt
new file mode 100644
index 000000000..42be6ba29
--- /dev/null
+++ b/Tests/RunCMake/file/TIMESTAMP-stdout.txt
@@ -0,0 +1 @@
+-- '[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z'
diff --git a/Tests/RunCMake/file/TIMESTAMP.cmake b/Tests/RunCMake/file/TIMESTAMP.cmake
new file mode 100644
index 000000000..2bd257721
--- /dev/null
+++ b/Tests/RunCMake/file/TIMESTAMP.cmake
@@ -0,0 +1,2 @@
+file(TIMESTAMP "TIMESTAMP.cmake" output UTC)
+message(STATUS "'${output}'")
diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake
index 23765d41c..296bb711b 100644
--- a/Tests/RunCMake/find_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake
@@ -7,6 +7,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=PrefixInPATH_File)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 000000000..4d496490d
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_file\):
+ find_file missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake
new file mode 100644
index 000000000..4800fe987
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_file(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 000000000..7e0eda09b
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_file\):
+ find_file command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake
new file mode 100644
index 000000000..ec0ce9a30
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_file(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt
new file mode 100644
index 000000000..6c8159bca
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/VALIDATOR-stdout.txt b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt
new file mode 100644
index 000000000..44fa77cb9
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE='FILE-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 000000000..b4125e6af
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_file\):
+ find_file command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake
new file mode 100644
index 000000000..c46588762
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_file(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_file/VALIDATOR.cmake b/Tests/RunCMake/find_file/VALIDATOR.cmake
new file mode 100644
index 000000000..72dd8f9cb
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_default
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ok
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ko
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index a912077cf..8b223b443 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -15,6 +15,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp")
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 000000000..6c04aa4dc
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_library\):
+ find_library missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake
new file mode 100644
index 000000000..516e54ed5
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_library(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 000000000..03e7df945
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_library\):
+ find_library command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake
new file mode 100644
index 000000000..fa90d723d
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_library(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt
new file mode 100644
index 000000000..721145068
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/VALIDATOR-stdout.txt b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt
new file mode 100644
index 000000000..bd2549bf3
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB='LIB-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 000000000..dc7ad9ee0
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_library\):
+ find_library command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake
new file mode 100644
index 000000000..9ac7ee0b0
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_library(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_library/VALIDATOR.cmake b/Tests/RunCMake/find_library/VALIDATOR.cmake
new file mode 100644
index 000000000..759394128
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR.cmake
@@ -0,0 +1,41 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_default
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_ok
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_ko
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 32e54d502..fa41fc180 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -55,6 +55,22 @@ run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
run_cmake(REGISTRY_VIEW-propagated)
+file(
+ GLOB SearchPaths_TEST_CASE_LIST
+ LIST_DIRECTORIES TRUE
+ "${RunCMake_SOURCE_DIR}/SearchPaths/*"
+ )
+foreach(TestCasePrefix IN LISTS SearchPaths_TEST_CASE_LIST)
+ if(IS_DIRECTORY "${TestCasePrefix}")
+ cmake_path(GET TestCasePrefix FILENAME TestSuffix)
+ run_cmake_with_options(
+ SearchPaths_${TestSuffix}
+ "-DSearchPaths_ROOT=${TestCasePrefix}"
+ "--debug-find-pkg=SearchPaths"
+ )
+ endif()
+endforeach()
+
if(UNIX
AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
)
diff --git a/Tests/RunCMake/find_package/SearchPaths.cmake b/Tests/RunCMake/find_package/SearchPaths.cmake
new file mode 100644
index 000000000..a5a10fced
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0074 NEW)
+find_package(SearchPaths REQUIRED CONFIG)
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt
new file mode 100644
index 000000000..fae13ef3e
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt
@@ -0,0 +1,10 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt
new file mode 100644
index 000000000..eba88c94a
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt
new file mode 100644
index 000000000..cebc169a2
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt
new file mode 100644
index 000000000..4e5d3f662
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt
new file mode 100644
index 000000000..f29054582
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt
new file mode 100644
index 000000000..32b9fcb7f
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt
new file mode 100644
index 000000000..7bf5cf8b6
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt
new file mode 100644
index 000000000..812c60728
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt
new file mode 100644
index 000000000..3592f72e8
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt
new file mode 100644
index 000000000..b196b7a7b
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt
new file mode 100644
index 000000000..17e039961
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt
new file mode 100644
index 000000000..ee01a50c5
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt
new file mode 100644
index 000000000..d6abd2ff6
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt
new file mode 100644
index 000000000..b578b2bab
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt
@@ -0,0 +1,14 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt
new file mode 100644
index 000000000..2f3f18aa2
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt
new file mode 100644
index 000000000..3eef00243
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt
new file mode 100644
index 000000000..c962f8bce
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt
@@ -0,0 +1,12 @@
+ find_package considered the following locations for SearchPaths's Config
+ module:
+
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/SearchPathsConfig\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/searchpaths-config\.cmake
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
+
+ The file was found at
+
+ .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake
diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake
new file mode 100644
index 000000000..d83131395
--- /dev/null
+++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake")
diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake
index 63cadc22f..9c76f2e46 100644
--- a/Tests/RunCMake/find_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake
@@ -7,6 +7,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
if(APPLE)
run_cmake(FrameworksWithSubdirs)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 000000000..1dfd06499
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_path\):
+ find_path missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake
new file mode 100644
index 000000000..bac275284
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_path(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 000000000..92ee17ee5
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_path\):
+ find_path command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake
new file mode 100644
index 000000000..62b44ed6c
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_path(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt
new file mode 100644
index 000000000..851353dc2
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
diff --git a/Tests/RunCMake/find_path/VALIDATOR-stdout.txt b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt
new file mode 100644
index 000000000..3fce03039
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- DIR='[^']+/Tests/RunCMake/find_path/include'
+-- DIR='[^']+/Tests/RunCMake/find_path/include'
+-- DIR='DIR-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 000000000..d3e05176a
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_path\):
+ find_path command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake
new file mode 100644
index 000000000..3fb55c526
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_path(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_path/VALIDATOR.cmake b/Tests/RunCMake/find_path/VALIDATOR.cmake
new file mode 100644
index 000000000..1e01250b1
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_default
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ok
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ko
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake
index d0ce8fcac..f8ecb8fed 100644
--- a/Tests/RunCMake/find_program/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake
@@ -9,6 +9,10 @@ run_cmake(NO_CACHE)
run_cmake(IgnorePrefixPath)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$")
run_cmake(WindowsCom)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 000000000..b8868af5b
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_program\):
+ find_program missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake
new file mode 100644
index 000000000..0d6a74f3b
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_program(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 000000000..1ae51481b
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_program\):
+ find_program command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake
new file mode 100644
index 000000000..43bb9ec31
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_program(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt
new file mode 100644
index 000000000..6704ed1f2
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
diff --git a/Tests/RunCMake/find_program/VALIDATOR-stdout.txt b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt
new file mode 100644
index 000000000..d434742d0
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- PROG='[^']+/Tests/RunCMake/find_program/A/testA'
+-- PROG='[^']+/Tests/RunCMake/find_program/A/testA'
+-- PROG='PROG-NOTFOUND'
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 000000000..a89ffa079
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_program\):
+ find_program command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake
new file mode 100644
index 000000000..96be5fdcd
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_program(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_program/VALIDATOR.cmake b/Tests/RunCMake/find_program/VALIDATOR.cmake
new file mode 100644
index 000000000..8be2b3906
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_default
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_ok
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_ko
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt
new file mode 100644
index 000000000..d082b8a12
--- /dev/null
+++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt
@@ -0,0 +1,12 @@
+^CMake Error at cmake_install.cmake:[0-9]+ \(file\):
+ file INSTALL cannot duplicate symlink
+
+ [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/new/dir
+
+ at
+
+ [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir
+
+ because: A directory already exists at that location
diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt
new file mode 100644
index 000000000..c520de1c9
--- /dev/null
+++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt
@@ -0,0 +1,12 @@
+-- Installing: [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir
+-- Installing: [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir/file
+-- Installing: [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk
+-- Installing: [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk
+-- (Up-to-date|Installing): [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk/file
+-- Installing: [^
+]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir
diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake b/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake
new file mode 100644
index 000000000..ac7a2cf4a
--- /dev/null
+++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake
@@ -0,0 +1,11 @@
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/old/dir)
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/old/dir/file "")
+file(CREATE_LINK dir ${CMAKE_CURRENT_BINARY_DIR}/old/lnk SYMBOLIC)
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/old/dir DESTINATION dest)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/old/lnk DESTINATION dest)
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/new/lnk)
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/new/lnk/file "")
+file(CREATE_LINK lnk ${CMAKE_CURRENT_BINARY_DIR}/new/dir SYMBOLIC)
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/new/lnk DESTINATION dest)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/new/dir DESTINATION dest)
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index 7c12d4a31..477ffe06c 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -175,6 +175,10 @@ run_install_test(FILES-PERMISSIONS)
run_install_test(TARGETS-RPATH)
run_install_test(InstallRequiredSystemLibraries)
+if(UNIX)
+ run_install_test(DIRECTORY-symlink-clobber)
+endif()
+
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle)
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework)
diff --git a/Tests/RunCMake/project/LanguagesDuplicate-check.cmake b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake
new file mode 100644
index 000000000..31c7da367
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake
@@ -0,0 +1,10 @@
+if(NOT actual_stderr MATCHES "The following language has been specified multiple times: C\n")
+ set(RunCMake_TEST_FAILED "'LANGUAGES C C C' should report only 'C' and only once.")
+endif()
+
+if(NOT actual_stderr MATCHES "The following languages have been specified multiple times: C, CXX\n")
+ if(RunCMake_TEST_FAILED)
+ string(APPEND RunCMake_TEST_FAILED "\n")
+ endif()
+ string(APPEND RunCMake_TEST_FAILED "'LANGUAGES C C CXX CXX' should report 'C' and 'CXX'.")
+endif()
diff --git a/Tests/RunCMake/project/LanguagesDuplicate.cmake b/Tests/RunCMake/project/LanguagesDuplicate.cmake
new file mode 100644
index 000000000..97a79d082
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesDuplicate.cmake
@@ -0,0 +1,11 @@
+cmake_policy(SET CMP0057 NEW)
+
+project(ProjectA C C C)
+project(ProjectB C C CXX CXX)
+
+get_property(langs GLOBAL PROPERTY ENABLED_LANGUAGES)
+foreach(lang C CXX)
+ if(NOT lang IN_LIST langs)
+ message(FATAL_ERROR "Expected language '${lang}' to be enabled.")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 945d9ed58..6d9f52f51 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -12,6 +12,11 @@ run_cmake_with_options(CodeInjection
if(CMake_TEST_RESOURCES)
run_cmake(ExplicitRC)
endif()
+
+set(RunCMake_DEFAULT_stderr .)
+run_cmake(LanguagesDuplicate)
+unset(RunCMake_DEFAULT_stderr)
+
run_cmake(LanguagesImplicit)
run_cmake(LanguagesEmpty)
run_cmake(LanguagesNONE)
diff --git a/Tests/RunCMake/pseudo_tidy.c b/Tests/RunCMake/pseudo_tidy.c
index 2feeb0fc9..a43133b8d 100644
--- a/Tests/RunCMake/pseudo_tidy.c
+++ b/Tests/RunCMake/pseudo_tidy.c
@@ -5,6 +5,16 @@ int main(int argc, char* argv[])
{
int i;
for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-p") == 0) {
+ // Ensure compile commands were not appended after the source file
+ for (++i; i < argc; ++i) {
+ if (strcmp(argv[i], "--") == 0) {
+ fprintf(stderr, "Command line arguments unexpectedly appended\n");
+ return 1;
+ }
+ }
+ return 0;
+ }
if (strcmp(argv[i], "-bad") == 0) {
fprintf(stdout, "stdout from bad command line arg '-bad'\n");
fprintf(stderr, "stderr from bad command line arg '-bad'\n");
diff --git a/Tests/RunCMake/return/CMP0140-NEW.cmake b/Tests/RunCMake/return/CMP0140-NEW.cmake
new file mode 100644
index 000000000..eb6b85c57
--- /dev/null
+++ b/Tests/RunCMake/return/CMP0140-NEW.cmake
@@ -0,0 +1,13 @@
+
+cmake_policy(SET CMP0140 NEW)
+
+function(FUNC)
+ set(VAR "set")
+ return(PROPAGATE VAR)
+endfunction()
+
+set(VAR "initial")
+func()
+if (NOT DEFINED VAR OR NOT VAR STREQUAL "set")
+ message(FATAL_ERROR "return(PROPAGATE) not handled correctly.")
+endif()
diff --git a/Tests/RunCMake/return/CMP0140-OLD.cmake b/Tests/RunCMake/return/CMP0140-OLD.cmake
new file mode 100644
index 000000000..8113a43f2
--- /dev/null
+++ b/Tests/RunCMake/return/CMP0140-OLD.cmake
@@ -0,0 +1,8 @@
+
+cmake_policy(SET CMP0140 OLD)
+
+function(FUNC)
+ return(PROPAGATE VAR)
+endfunction()
+
+func()
diff --git a/Tests/RunCMake/return/CMP0140-WARN-result.txt b/Tests/RunCMake/return/CMP0140-WARN-result.txt
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/Tests/RunCMake/return/CMP0140-WARN-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/return/CMP0140-WARN-stderr.txt b/Tests/RunCMake/return/CMP0140-WARN-stderr.txt
new file mode 100644
index 000000000..ed4beb6f5
--- /dev/null
+++ b/Tests/RunCMake/return/CMP0140-WARN-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\) at CMP0140-WARN.cmake:[0-9]+ \(return\):
+ Policy CMP0140 is not set: The return\(\) command checks its arguments. Run
+ "cmake --help-policy CMP0140" for policy details. Use the cmake_policy
+ command to set the policy and suppress this warning.
+
+ return\(\) checks its arguments when the policy is set to NEW. Since the
+ policy is not set the OLD behavior will be used so the arguments will be
+ ignored.
+Call Stack \(most recent call first\):
+ CMP0140-WARN.cmake:[0-9]+ \(func\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/return/CMP0140-WARN.cmake b/Tests/RunCMake/return/CMP0140-WARN.cmake
new file mode 100644
index 000000000..df2fc887b
--- /dev/null
+++ b/Tests/RunCMake/return/CMP0140-WARN.cmake
@@ -0,0 +1,8 @@
+
+cmake_policy(VERSION 3.1)
+
+function(FUNC)
+ return(PROPAGATE VAR)
+endfunction()
+
+func()
diff --git a/Tests/RunCMake/return/CMakeLists.txt b/Tests/RunCMake/return/CMakeLists.txt
index ef2163c29..6cc903fc7 100644
--- a/Tests/RunCMake/return/CMakeLists.txt
+++ b/Tests/RunCMake/return/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.25)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/return/PropagateFromDirectory.cmake b/Tests/RunCMake/return/PropagateFromDirectory.cmake
new file mode 100644
index 000000000..9c820bb7d
--- /dev/null
+++ b/Tests/RunCMake/return/PropagateFromDirectory.cmake
@@ -0,0 +1,10 @@
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+
+add_subdirectory(subdir)
+
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC1")
+endif()
diff --git a/Tests/RunCMake/return/PropagateFromFunction.cmake b/Tests/RunCMake/return/PropagateFromFunction.cmake
new file mode 100644
index 000000000..1c12bc198
--- /dev/null
+++ b/Tests/RunCMake/return/PropagateFromFunction.cmake
@@ -0,0 +1,142 @@
+
+function(FUNC1)
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func1()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC1")
+endif()
+
+
+function(FUNC2)
+ block()
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endblock()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func2()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC2")
+endif()
+
+
+function(FUNC3)
+ block(SCOPE_FOR POLICIES)
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endblock()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func3()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC3")
+endif()
+
+
+function(FUNC4)
+ while(TRUE)
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endwhile()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func4()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC4")
+endif()
+
+
+function(FUNC5)
+ foreach(item IN ITEMS A B)
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endforeach()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func5()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC5")
+endif()
+
+
+function(FUNC6)
+ if(TRUE)
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endif()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func6()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC6")
+endif()
+
+
+function(FUNC7)
+ if(FALSE)
+ else()
+ set(VAR1 "set")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endif()
+endfunction()
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+func7()
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for FUNC7")
+endif()
+
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+cmake_language(CALL func7)
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for cmake_language(CALL FUNC7)")
+endif()
+
+
+set(VAR1 "initial")
+set(VAR2 "initial")
+cmake_language(EVAL CODE "
+ function(FUNC8)
+ set(VAR1 \"set\")
+ unset(VAR2)
+ return(PROPAGATE VAR1 VAR2)
+ endfunction()
+
+ func8()")
+if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set")
+ OR DEFINED VAR2)
+ message(SEND_ERROR "erroneous propagation for cmake_language(EVAL CODE)")
+endif()
diff --git a/Tests/RunCMake/return/PropagateNothing.cmake b/Tests/RunCMake/return/PropagateNothing.cmake
new file mode 100644
index 000000000..0ace58e45
--- /dev/null
+++ b/Tests/RunCMake/return/PropagateNothing.cmake
@@ -0,0 +1,2 @@
+
+return(PROPAGATE)
diff --git a/Tests/RunCMake/return/RunCMakeTest.cmake b/Tests/RunCMake/return/RunCMakeTest.cmake
index 2cc6c9d32..f9e06a53c 100644
--- a/Tests/RunCMake/return/RunCMakeTest.cmake
+++ b/Tests/RunCMake/return/RunCMakeTest.cmake
@@ -1,3 +1,12 @@
include(RunCMake)
run_cmake(ReturnFromForeach)
+
+run_cmake(WrongArgument)
+run_cmake(PropagateNothing)
+run_cmake(PropagateFromFunction)
+run_cmake(PropagateFromDirectory)
+
+run_cmake(CMP0140-NEW)
+run_cmake(CMP0140-OLD)
+run_cmake(CMP0140-WARN)
diff --git a/Tests/RunCMake/return/WrongArgument-result.txt b/Tests/RunCMake/return/WrongArgument-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/return/WrongArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/return/WrongArgument-stderr.txt b/Tests/RunCMake/return/WrongArgument-stderr.txt
new file mode 100644
index 000000000..4d1c5ad87
--- /dev/null
+++ b/Tests/RunCMake/return/WrongArgument-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at WrongArgument.cmake:[0-9]+ \(return\):
+ return called with unsupported argument "WRONG_ARG"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/return/WrongArgument.cmake b/Tests/RunCMake/return/WrongArgument.cmake
new file mode 100644
index 000000000..d03b19fa4
--- /dev/null
+++ b/Tests/RunCMake/return/WrongArgument.cmake
@@ -0,0 +1,2 @@
+
+return(WRONG_ARG)
diff --git a/Tests/RunCMake/return/subdir/CMakeLists.txt b/Tests/RunCMake/return/subdir/CMakeLists.txt
new file mode 100644
index 000000000..e575d4704
--- /dev/null
+++ b/Tests/RunCMake/return/subdir/CMakeLists.txt
@@ -0,0 +1,5 @@
+
+set(VAR1 "set")
+unset(VAR2)
+
+return(PROPAGATE VAR1 VAR2)
diff --git a/Tests/RunCMake/showIncludes.c b/Tests/RunCMake/showIncludes.c
new file mode 100644
index 000000000..23b38458d
--- /dev/null
+++ b/Tests/RunCMake/showIncludes.c
@@ -0,0 +1,33 @@
+#if defined(_MSC_VER) && _MSC_VER >= 1928
+# pragma warning(disable : 5105) /* macro expansion warning in windows.h */
+#endif
+#include <windows.h>
+
+#include <stdio.h>
+
+int main()
+{
+ /* 'cl /showIncludes' encodes output in the console output code page. */
+ unsigned int cp = GetConsoleOutputCP();
+ printf("Console output code page: %u\n", cp);
+ printf("Console input code page: %u\n", GetConsoleCP());
+ printf("ANSI code page: %u\n", GetACP());
+ printf("OEM code page: %u\n", GetOEMCP());
+
+ if (cp == 54936 || cp == 936) {
+ /* VSLANG=2052 */
+ printf("\xd7\xa2\xd2\xe2: "
+ "\xb0\xfc\xba\xac\xce\xc4\xbc\xfe:\n");
+ return 0;
+ }
+
+ if (cp == 65001) {
+ /* VSLANG=2052 */
+ printf("\xe6\xb3\xa8\xe6\x84\x8f: "
+ "\xe5\x8c\x85\xe5\x90\xab\xe6\x96\x87\xe4\xbb\xb6:\n");
+ return 0;
+ }
+
+ fprintf(stderr, "No example showIncludes for console's output code page.\n");
+ return 1;
+}
diff --git a/Tests/RunCMake/string/JSON.cmake b/Tests/RunCMake/string/JSON.cmake
index ab4194d26..255c16a56 100644
--- a/Tests/RunCMake/string/JSON.cmake
+++ b/Tests/RunCMake/string/JSON.cmake
@@ -129,7 +129,7 @@ assert_strequal("${error}" "member '0' not found")
string(JSON result ERROR_VARIABLE error GET "${json1}" array 10)
assert_strequal("${result}" "array-10-NOTFOUND")
-assert_strequal("${error}" "expected an index less then 4 got '10'")
+assert_strequal("${error}" "expected an index less than 4 got '10'")
string(JSON result ERROR_VARIABLE error GET "${json1}" array 2 some notThere)
assert_strequal("${result}" "array-2-some-notThere-NOTFOUND")
@@ -240,7 +240,7 @@ endif()
string(JSON result ERROR_VARIABLE error MEMBER "${json1}" values 100)
assert_strequal("${result}" "values-100-NOTFOUND")
-assert_strequal("${error}" "expected an index less then 5 got '100'")
+assert_strequal("${error}" "expected an index less than 5 got '100'")
# Test length loops
string(JSON arrayLength ERROR_VARIABLE error LENGTH "${json1}" types array)
@@ -301,7 +301,7 @@ assert_json_equal("${error}" "${result}"
string(JSON result ERROR_VARIABLE error REMOVE ${json2} array 100)
assert_strequal("${result}" "array-100-NOTFOUND")
-assert_strequal("${error}" "expected an index less then 4 got '100'")
+assert_strequal("${error}" "expected an index less than 4 got '100'")
# Test SET
string(JSON result ERROR_VARIABLE error SET ${json2} new 5)
diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt
new file mode 100644
index 000000000..f04e43ff2
--- /dev/null
+++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0101-BEFORE_keyword.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0101 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
index 021de413b..9b6581c51 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
@@ -90,12 +90,22 @@ if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES
run_cmake_target(apple_framework target-framework main-target-framework)
run_cmake_target(apple_framework target-reexport_framework main-target-reexport_framework)
run_cmake_target(apple_framework target-weak_framework main-target-weak_framework)
+
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG AND (NOT XCODE OR XCODE_VERSION GREATER_EQUAL 13))
+ run_cmake_target(apple_framework target-framework-postfix main-target-framework-postfix)
+ run_cmake_target(apple_framework target-reexport_framework-postfix main-target-reexport_framework-postfix)
+ run_cmake_target(apple_framework target-weak_framework-postfix main-target-weak_framework-postfix)
+ endif()
endif()
if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION GREATER_EQUAL "12")
run_cmake_target(apple_framework needed_framework main-needed_framework)
run_cmake_target(apple_framework target-needed_framework main-target-needed_framework)
+
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG AND (NOT XCODE OR XCODE_VERSION GREATER_EQUAL 13))
+ run_cmake_target(apple_framework target-needed_framework-postfix main-target-needed_framework-postfix)
+ endif()
endif()
# Apple library features
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake
index e9a93e9fc..ca0e72d7e 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake
@@ -59,3 +59,33 @@ target_link_libraries(main-target-reexport_framework PRIVATE "$<LINK_LIBRARY:FRA
# feature WEAK_FRAMEWORK
add_executable(main-target-weak_framework main.mm)
target_link_libraries(main-target-weak_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework>")
+
+
+
+get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTI_CONFIG)
+ add_library(target-framework-postfix SHARED foo.mm)
+ set_target_properties(target-framework-postfix PROPERTIES FRAMEWORK TRUE
+ FRAMEWORK_MULTI_CONFIG_POSTFIX_RELEASE "_release")
+ target_link_libraries(target-framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>")
+
+
+ # feature FRAMEWORK
+ add_executable(main-target-framework-postfix main.mm)
+ target_link_libraries(main-target-framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:FRAMEWORK,target-framework-postfix>")
+
+
+ # feature NEEDED_FRAMEWORK
+ add_executable(main-target-needed_framework-postfix main.mm)
+ target_link_libraries(main-target-needed_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:NEEDED_FRAMEWORK,target-framework-postfix>")
+
+
+ # feature REEXPORT_FRAMEWORK
+ add_executable(main-target-reexport_framework-postfix main.mm)
+ target_link_libraries(main-target-reexport_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework-postfix>")
+
+
+ # feature WEAK_FRAMEWORK
+ add_executable(main-target-weak_framework-postfix main.mm)
+ target_link_libraries(main-target-weak_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework-postfix>")
+endif()
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt
new file mode 100644
index 000000000..042d67df6
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt
@@ -0,0 +1,12 @@
+^CMake Warning \(dev\) at FileSetDefaultWrongTypeExperimental.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetDefaultWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or
+ "CXX_MODULE_HEADER_UNITS"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake
new file mode 100644
index 000000000..5ade637df
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+add_library(lib1 STATIC empty.c)
+target_sources(lib1 PRIVATE FILE_SET UNKNOWN)
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt
new file mode 100644
index 000000000..a1b784fa2
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt
@@ -0,0 +1,12 @@
+^CMake Warning \(dev\) at FileSetWrongTypeExperimental.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or
+ "CXX_MODULE_HEADER_UNITS"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake
new file mode 100644
index 000000000..332441c82
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+add_library(lib1 STATIC empty.c)
+target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN)
diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
index 6a3c7b9c6..7c67c3f47 100644
--- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
@@ -26,6 +26,8 @@ run_cmake(FileSetProperties)
run_cmake(FileSetNoType)
run_cmake(FileSetWrongType)
run_cmake(FileSetDefaultWrongType)
+run_cmake(FileSetWrongTypeExperimental)
+run_cmake(FileSetDefaultWrongTypeExperimental)
run_cmake(FileSetChangeScope)
run_cmake(FileSetChangeType)
run_cmake(FileSetWrongBaseDirs)
diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt
index 652bcfcd1..4e41a19dc 100644
--- a/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt
+++ b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at BadLinkLibraries.cmake:2 \(try_compile\):
+CMake Error at BadLinkLibraries.cmake:[0-9]+ \(try_compile\):
Only libraries may be used as try_compile or try_run IMPORTED
LINK_LIBRARIES. Got not_a_library of type UTILITY.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries.cmake b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake
index e8b5add87..b758e23cd 100644
--- a/Tests/RunCMake/try_compile/BadLinkLibraries.cmake
+++ b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake
@@ -1,3 +1,7 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
add_custom_target(not_a_library)
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
LINK_LIBRARIES not_a_library)
diff --git a/Tests/RunCMake/try_compile/BadSources1-stderr.txt b/Tests/RunCMake/try_compile/BadSources1-stderr.txt
index 864a2942c..ddcba4f35 100644
--- a/Tests/RunCMake/try_compile/BadSources1-stderr.txt
+++ b/Tests/RunCMake/try_compile/BadSources1-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at BadSources1.cmake:1 \(try_compile\):
+CMake Error at BadSources1.cmake:[0-9]+ \(try_compile\):
Unknown extension ".c" for file
.*/Tests/RunCMake/try_compile/src.c
diff --git a/Tests/RunCMake/try_compile/BadSources1.cmake b/Tests/RunCMake/try_compile/BadSources1.cmake
index aa4dc5ee5..c95935d3a 100644
--- a/Tests/RunCMake/try_compile/BadSources1.cmake
+++ b/Tests/RunCMake/try_compile/BadSources1.cmake
@@ -1 +1,3 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_compile/BadSources2-stderr.txt b/Tests/RunCMake/try_compile/BadSources2-stderr.txt
index 3313f9933..953dd9ccc 100644
--- a/Tests/RunCMake/try_compile/BadSources2-stderr.txt
+++ b/Tests/RunCMake/try_compile/BadSources2-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at BadSources2.cmake:2 \(try_compile\):
+CMake Error at BadSources2.cmake:[0-9]+ \(try_compile\):
Unknown extension ".cxx" for file
.*/Tests/RunCMake/try_compile/src.cxx
diff --git a/Tests/RunCMake/try_compile/BadSources2.cmake b/Tests/RunCMake/try_compile/BadSources2.cmake
index ed2b0364d..3f22bb6f2 100644
--- a/Tests/RunCMake/try_compile/BadSources2.cmake
+++ b/Tests/RunCMake/try_compile/BadSources2.cmake
@@ -1,5 +1,6 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
enable_language(C)
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
)
diff --git a/Tests/RunCMake/try_compile/BinDirEmpty-result.txt b/Tests/RunCMake/try_compile/BinDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt
new file mode 100644
index 000000000..b1f5ae3b4
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at BinDirEmpty.cmake:[0-9]+ \(try_compile\):
+ No <bindir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_compile/BinDirEmpty.cmake b/Tests/RunCMake/try_compile/BinDirEmpty.cmake
new file mode 100644
index 000000000..7bea43d85
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirEmpty.cmake
@@ -0,0 +1 @@
+try_compile(resultVar "" ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_compile/BinDirRelative-result.txt b/Tests/RunCMake/try_compile/BinDirRelative-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirRelative-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt b/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt
new file mode 100644
index 000000000..a7b6302d0
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at BinDirRelative.cmake:[0-9]+ \(try_compile\):
+ <bindir> is not an absolute path:
+
+ 'bin_dir_relative'
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_compile/BinDirRelative.cmake b/Tests/RunCMake/try_compile/BinDirRelative.cmake
new file mode 100644
index 000000000..8deda11ee
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BinDirRelative.cmake
@@ -0,0 +1 @@
+try_compile(resultVar bin_dir_relative ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_compile/BuildType.cmake b/Tests/RunCMake/try_compile/BuildType.cmake
new file mode 100644
index 000000000..8d7e3bef8
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BuildType.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+set(CMAKE_BUILD_TYPE RelWithDebInfo)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT
+ ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin"
+ )
diff --git a/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake
new file mode 100644
index 000000000..a822156e2
--- /dev/null
+++ b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+set(CMAKE_BUILD_TYPE RelWithDebInfo)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT
+ ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin"
+ CMAKE_FLAGS "-DCMAKE_BUILD_TYPE=Release"
+ )
diff --git a/Tests/RunCMake/try_compile/CStandard-stderr.txt b/Tests/RunCMake/try_compile/CStandard-stderr.txt
index 209afcc56..c3c48a16c 100644
--- a/Tests/RunCMake/try_compile/CStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/CStandard-stderr.txt
@@ -1,4 +1,4 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/CStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^CMake Error at .*/Tests/RunCMake/try_compile/CStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\):
C_STANDARD is set to invalid value '3'
+
CMake Error at CStandard.cmake:[0-9]+ \(try_compile\):
diff --git a/Tests/RunCMake/try_compile/CStandard.cmake b/Tests/RunCMake/try_compile/CStandard.cmake
index 2849ed4fd..6ac04db4a 100644
--- a/Tests/RunCMake/try_compile/CStandard.cmake
+++ b/Tests/RunCMake/try_compile/CStandard.cmake
@@ -1,7 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
C_STANDARD 3
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/CStandardGNU.cmake b/Tests/RunCMake/try_compile/CStandardGNU.cmake
index 79ae87445..10a438403 100644
--- a/Tests/RunCMake/try_compile/CStandardGNU.cmake
+++ b/Tests/RunCMake/try_compile/CStandardGNU.cmake
@@ -1,23 +1,30 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
C_STANDARD 99
C_STANDARD_REQUIRED 1
C_EXTENSIONS 0
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
cmake_policy(SET CMP0067 NEW)
+
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED 1)
set(CMAKE_C_EXTENSIONS 0)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
diff --git a/Tests/RunCMake/try_compile/CStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake
index 97e72ea40..f4dd5aebe 100644
--- a/Tests/RunCMake/try_compile/CStandardNoDefault.cmake
+++ b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake
@@ -1,9 +1,13 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
C_STANDARD 3 # bogus, but not used
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt
index 5d09c0c61..8c4930287 100644
--- a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt
+++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at CopyFileErrorNoCopyFile.cmake:1 \(try_compile\):
+CMake Error at CopyFileErrorNoCopyFile.cmake:[0-9]+ \(try_compile\):
COPY_FILE_ERROR may be used only with COPY_FILE
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake
index 8d7cb0e7f..8d15b3db1 100644
--- a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake
+++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
COPY_FILE_ERROR _copied)
diff --git a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt
index bcf95d546..52dff8f33 100644
--- a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt
@@ -1,4 +1,4 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\):
CUDA_STANDARD is set to invalid value '4'
+
CMake Error at CudaStandard.cmake:[0-9]+ \(try_compile\):
diff --git a/Tests/RunCMake/try_compile/CudaStandard.cmake b/Tests/RunCMake/try_compile/CudaStandard.cmake
index a230424bf..0be89bef3 100644
--- a/Tests/RunCMake/try_compile/CudaStandard.cmake
+++ b/Tests/RunCMake/try_compile/CudaStandard.cmake
@@ -1,7 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(CUDA)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cu
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cu
CUDA_STANDARD 4
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
index ec7245fdd..55a06e294 100644
--- a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
@@ -1,6 +1,17 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^(CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:
+ The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid
+ value: "3".
+
+
+)?CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\):
CXX_STANDARD is set to invalid value '3'
-+
+
+(
+CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:
+ The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid
+ value: "3".
+
+)?
CMake Error at CxxStandard.cmake:[0-9]+ \(try_compile\):
Failed to generate test project build system.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/try_compile/CxxStandard.cmake b/Tests/RunCMake/try_compile/CxxStandard.cmake
index bcb49b9b3..e5b4e7818 100644
--- a/Tests/RunCMake/try_compile/CxxStandard.cmake
+++ b/Tests/RunCMake/try_compile/CxxStandard.cmake
@@ -1,7 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(CXX)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
CXX_STANDARD 3
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/CxxStandardGNU.cmake b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake
index e714fe4d0..552d99d6b 100644
--- a/Tests/RunCMake/try_compile/CxxStandardGNU.cmake
+++ b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake
@@ -1,23 +1,30 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(CXX)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
CXX_STANDARD 11
CXX_STANDARD_REQUIRED 1
CXX_EXTENSIONS 0
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
cmake_policy(SET CMP0067 NEW)
+
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED 1)
set(CMAKE_CXX_EXTENSIONS 0)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
diff --git a/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake
index 35caa9d09..e0ebfeec7 100644
--- a/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake
+++ b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake
@@ -1,9 +1,13 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(CXX)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
CXX_STANDARD 3 # bogus, but not used
OUTPUT_VARIABLE out
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
diff --git a/Tests/RunCMake/try_compile/EmptyListArgs.cmake b/Tests/RunCMake/try_compile/EmptyListArgs.cmake
new file mode 100644
index 000000000..5cd7465ff
--- /dev/null
+++ b/Tests/RunCMake/try_compile/EmptyListArgs.cmake
@@ -0,0 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+enable_language(C)
+
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ CMAKE_FLAGS # no values
+ COMPILE_DEFINITIONS # no values
+ LINK_LIBRARIES # no values
+ LINK_OPTIONS # no values
+ )
diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt b/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt b/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt
new file mode 100644
index 000000000..b1344bd43
--- /dev/null
+++ b/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at EmptyValueArgs.cmake:[0-9]+ \(try_compile\):
+ COPY_FILE must be followed by a file path
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at EmptyValueArgs.cmake:[0-9]+ \(try_compile\):
+ COPY_FILE_ERROR must be followed by a variable name
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs.cmake b/Tests/RunCMake/try_compile/EmptyValueArgs.cmake
new file mode 100644
index 000000000..fda4f1023
--- /dev/null
+++ b/Tests/RunCMake/try_compile/EmptyValueArgs.cmake
@@ -0,0 +1,7 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "")
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "x" COPY_FILE_ERROR "")
diff --git a/Tests/RunCMake/try_compile/EnvConfig.cmake b/Tests/RunCMake/try_compile/EnvConfig.cmake
index 4040c593d..6e668259d 100644
--- a/Tests/RunCMake/try_compile/EnvConfig.cmake
+++ b/Tests/RunCMake/try_compile/EnvConfig.cmake
@@ -1,3 +1,5 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
set(ENV{CMAKE_BUILD_TYPE} "Bad")
@@ -6,8 +8,8 @@ set(ENV{CMAKE_CONFIGURATION_TYPES} "Bad;Debug")
add_library(tc_defs INTERFACE IMPORTED)
target_compile_definitions(tc_defs INTERFACE "TC_CONFIG_$<UPPER_CASE:$<CONFIG>>")
-try_compile(ENV_CONFIG_RESULT "${CMAKE_BINARY_DIR}"
- SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/EnvConfig.c"
+try_compile(ENV_CONFIG_RESULT "${try_compile_bindir_or_SOURCES}"
+ ${try_compile_redundant_SOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/EnvConfig.c"
COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/EnvConfig.bin"
OUTPUT_VARIABLE tc_output
LINK_LIBRARIES tc_defs
diff --git a/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake b/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
index 6d29069cd..1ead4c28a 100644
--- a/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
+++ b/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
@@ -1,8 +1,12 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(ISPC)
-set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
- avx512skx-i32x16)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+
+set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 avx512skx-i32x16)
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake b/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
index 7f59c1451..e08e25f23 100644
--- a/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
+++ b/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
@@ -1,11 +1,16 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(ISPC)
-set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
- avx512skx-i32x16)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+
+set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 avx512skx-i32x16)
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
+
if(NOT result)
message(FATAL_ERROR "making Ninja and Ninja Multi-Config behave the same")
endif()
diff --git a/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake b/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
index c1ab6f24e..2276bd3be 100644
--- a/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
+++ b/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
@@ -1,7 +1,12 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(ISPC)
+
set(CMAKE_ISPC_INSTRUCTION_SETS "avxknl-i32x16")
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/ISPCTargets.cmake b/Tests/RunCMake/try_compile/ISPCTargets.cmake
index 0d3bd4369..bd455691d 100644
--- a/Tests/RunCMake/try_compile/ISPCTargets.cmake
+++ b/Tests/RunCMake/try_compile/ISPCTargets.cmake
@@ -1,7 +1,12 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(ISPC)
+
set(CMAKE_ISPC_INSTRUCTION_SETS avx512knl-i32x16 avx512skx-i32x16)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/NoArgs-stderr.txt b/Tests/RunCMake/try_compile/NoArgs-stderr.txt
index 8808fd19a..422858006 100644
--- a/Tests/RunCMake/try_compile/NoArgs-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoArgs-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NoArgs.cmake:1 \(try_compile\):
- try_compile unknown error.
+CMake Error at NoArgs.cmake:[0-9]+ \(try_compile\):
+ The try_compile\(\) command requires at least 3 arguments.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCStandard-result.txt b/Tests/RunCMake/try_compile/NoCStandard-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/NoCStandard-stderr.txt b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt
new file mode 100644
index 000000000..e0bb9ed14
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at NoCStandard.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "C_STANDARD":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCStandard.cmake b/Tests/RunCMake/try_compile/NoCStandard.cmake
new file mode 100644
index 000000000..e0d0478d2
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ C_STANDARD)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
index d65d94883..55ba687c0 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoCopyFile.cmake:1 \(try_compile\):
- COPY_FILE must be followed by a file path
+CMake Error at NoCopyFile.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "COPY_FILE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile.cmake b/Tests/RunCMake/try_compile/NoCopyFile.cmake
index 8c648ff32..270dff9b2 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile.cmake
+++ b/Tests/RunCMake/try_compile/NoCopyFile.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
COPY_FILE)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
index e88952475..008d4e9a4 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoCopyFile2.cmake:1 \(try_compile\):
- COPY_FILE must be followed by a file path
+CMake Error at NoCopyFile2.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "COPY_FILE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile2.cmake b/Tests/RunCMake/try_compile/NoCopyFile2.cmake
index 04b7f6882..2ea81824a 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile2.cmake
+++ b/Tests/RunCMake/try_compile/NoCopyFile2.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
COPY_FILE CMAKE_FLAGS -DA=B)
diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
index ed552fd8e..7ca185d9e 100644
--- a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoCopyFileError.cmake:1 \(try_compile\):
- COPY_FILE_ERROR must be followed by a variable name
+CMake Error at NoCopyFileError.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "COPY_FILE_ERROR":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCopyFileError.cmake b/Tests/RunCMake/try_compile/NoCopyFileError.cmake
index d4d69ee01..1a56e86e8 100644
--- a/Tests/RunCMake/try_compile/NoCopyFileError.cmake
+++ b/Tests/RunCMake/try_compile/NoCopyFileError.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copied.bin COPY_FILE_ERROR)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
index 18ad751cf..ec29f0bee 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoOutputVariable.cmake:1 \(try_compile\):
- OUTPUT_VARIABLE must be followed by a variable name
+CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable.cmake b/Tests/RunCMake/try_compile/NoOutputVariable.cmake
index 3b9cb345b..13dc4b49f 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable.cmake
+++ b/Tests/RunCMake/try_compile/NoOutputVariable.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
index 8b2cc254c..dd345593c 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoOutputVariable2.cmake:1 \(try_compile\):
- OUTPUT_VARIABLE must be followed by a variable name
+CMake Error at NoOutputVariable2.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2.cmake b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake
index ad9ac9ac5..4d5dda399 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable2.cmake
+++ b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake
@@ -1,2 +1,4 @@
-try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE CMAKE_FLAGS -DA=B)
diff --git a/Tests/RunCMake/try_compile/NoSources-stderr.txt b/Tests/RunCMake/try_compile/NoSources-stderr.txt
index 023032b60..55603dca1 100644
--- a/Tests/RunCMake/try_compile/NoSources-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoSources-stderr.txt
@@ -1,4 +1,7 @@
-CMake Error at NoSources.cmake:1 \(try_compile\):
- SOURCES must be followed by at least one source file
+CMake Error at NoSources.cmake:[0-9]+ \(try_compile\):
+ Error after keyword "SOURCES":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt
index 025e65868..dcd5c7a76 100644
--- a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt
+++ b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonSourceCompileDefinitions.cmake:1 \(try_compile\):
- COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE
+CMake Error at NonSourceCompileDefinitions.cmake:[0-9]+ \(try_compile\):
+ COMPILE_DEFINITIONS allowed only in source file signature
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt
index f5893e19f..1b7dfeb24 100644
--- a/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt
+++ b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonSourceCopyFile.cmake:1 \(try_compile\):
- COPY_FILE specified on a srcdir type TRY_COMPILE
+CMake Error at NonSourceCopyFile.cmake:[0-9]+ \(try_compile\):
+ COPY_FILE allowed only in source file signature
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt
index f1b4df9e0..59f1d73f9 100644
--- a/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt
@@ -1,4 +1,4 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/ObjCStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^CMake Error at .*/Tests/RunCMake/try_compile/ObjCStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\):
OBJC_STANDARD is set to invalid value '3'
+
CMake Error at ObjCStandard.cmake:[0-9]+ \(try_compile\):
diff --git a/Tests/RunCMake/try_compile/ObjCStandard.cmake b/Tests/RunCMake/try_compile/ObjCStandard.cmake
index b2066f957..a691dddfc 100644
--- a/Tests/RunCMake/try_compile/ObjCStandard.cmake
+++ b/Tests/RunCMake/try_compile/ObjCStandard.cmake
@@ -1,7 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(OBJC)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.m
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.m
OBJC_STANDARD 3
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt
index a2f91b48f..21fa20f91 100644
--- a/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt
@@ -1,4 +1,4 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/ObjCxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^CMake Error at .*/Tests/RunCMake/try_compile/ObjCxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\):
OBJCXX_STANDARD is set to invalid value '3'
+
CMake Error at ObjCxxStandard.cmake:[0-9]+ \(try_compile\):
diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard.cmake b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake
index 1221805c0..b03f56016 100644
--- a/Tests/RunCMake/try_compile/ObjCxxStandard.cmake
+++ b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake
@@ -1,7 +1,11 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(OBJCXX)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.mm
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.mm
OBJCXX_STANDARD 3
OUTPUT_VARIABLE out
)
+
message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt
new file mode 100644
index 000000000..e9ec4509e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at OldProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\):
+ No <bindir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake
new file mode 100644
index 000000000..fa922d922
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake
@@ -0,0 +1 @@
+try_compile(RESULT "" ${CMAKE_CURRENT_SOURCE_DIR}/proj Foo)
diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt
new file mode 100644
index 000000000..47dd60f8d
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at OldProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\):
+ No <srcdir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake
new file mode 100644
index 000000000..dfbfba6af
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake
@@ -0,0 +1 @@
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} "" Foo)
diff --git a/Tests/RunCMake/try_compile/OneArg-stderr.txt b/Tests/RunCMake/try_compile/OneArg-stderr.txt
index 12835bed6..a2e983efb 100644
--- a/Tests/RunCMake/try_compile/OneArg-stderr.txt
+++ b/Tests/RunCMake/try_compile/OneArg-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at OneArg.cmake:1 \(try_compile\):
- try_compile unknown error.
+CMake Error at OneArg.cmake:[0-9]+ \(try_compile\):
+ The try_compile\(\) command requires at least 3 arguments.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake
new file mode 100644
index 000000000..1214bbb18
--- /dev/null
+++ b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+set(CMAKE_BUILD_TYPE RelWithDebInfo)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+try_compile(RESULT
+ ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin"
+ CMAKE_FLAGS "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=bin"
+ )
diff --git a/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt b/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt
new file mode 100644
index 000000000..4a42b2d5b
--- /dev/null
+++ b/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Debug Log at [^
+]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\):
+ Executing try_compile \(CMAKE_C_ABI_COMPILED\) in:
+
+ [^
+]*/Tests/RunCMake/try_compile/PlatformVariables-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)
+ PlatformVariables.cmake:[0-9]+ \(enable_language\)
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt
new file mode 100644
index 000000000..57a2bd0d2
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at ProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\):
+ No <bindir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake b/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake
new file mode 100644
index 000000000..e867cc693
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake
@@ -0,0 +1,4 @@
+try_compile(RESULT PROJECT Foo
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj
+ BINARY_DIR ""
+ )
diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt b/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt b/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt
new file mode 100644
index 000000000..45241c930
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt
@@ -0,0 +1,7 @@
+CMake Warning \(dev\) at ProjectCopyFile.cmake:[0-9]+ \(try_compile\):
+ Unknown arguments:
+
+ "COPY_FILE"
+ "result"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile.cmake b/Tests/RunCMake/try_compile/ProjectCopyFile.cmake
new file mode 100644
index 000000000..6bfec994f
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectCopyFile.cmake
@@ -0,0 +1,4 @@
+try_compile(RESULT
+ PROJECT TestProject
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj
+ COPY_FILE result)
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt
new file mode 100644
index 000000000..dc6f3543d
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at ProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\):
+ No <srcdir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake
new file mode 100644
index 000000000..ac33ed0df
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake
@@ -0,0 +1 @@
+try_compile(RESULT PROJECT Foo SOURCE_DIR "")
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt
new file mode 100644
index 000000000..af6edd528
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at ProjectSrcDirMissing.cmake:[0-9]+ \(try_compile\):
+ No <srcdir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake b/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake
new file mode 100644
index 000000000..e32cdf4a3
--- /dev/null
+++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake
@@ -0,0 +1 @@
+try_compile(RESULT PROJECT Foo)
diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
index 3cfbfbff7..724547126 100644
--- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
@@ -1,32 +1,39 @@
include(RunCMake)
-run_cmake(CopyFileErrorNoCopyFile)
run_cmake(NoArgs)
run_cmake(OneArg)
run_cmake(TwoArgs)
-run_cmake(NoCopyFile)
-run_cmake(NoCopyFile2)
-run_cmake(NoCopyFileError)
-run_cmake(NoOutputVariable)
-run_cmake(NoOutputVariable2)
run_cmake(NoSources)
-run_cmake(BadLinkLibraries)
-run_cmake(BadSources1)
-run_cmake(BadSources2)
+run_cmake(BinDirEmpty)
+run_cmake(BinDirRelative)
+run_cmake(ProjectSrcDirMissing)
+run_cmake(ProjectSrcDirEmpty)
+run_cmake(ProjectBinDirEmpty)
+run_cmake(OldProjectSrcDirEmpty)
+run_cmake(OldProjectBinDirEmpty)
+
+set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=old_signature.cmake)
+include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
+unset(RunCMake_TEST_OPTIONS)
+
+set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=new_signature.cmake)
+include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
+unset(RunCMake_TEST_OPTIONS)
+
+run_cmake(SourceFromOneArg)
+run_cmake(SourceFromThreeArgs)
+run_cmake(SourceFromBadName)
+run_cmake(SourceFromBadFile)
+
+run_cmake(ProjectCopyFile)
run_cmake(NonSourceCopyFile)
run_cmake(NonSourceCompileDefinitions)
-run_cmake(EnvConfig)
-
set(RunCMake_TEST_OPTIONS --debug-trycompile)
run_cmake(PlatformVariables)
run_cmake(WarnDeprecated)
unset(RunCMake_TEST_OPTIONS)
-run_cmake(TargetTypeExe)
-run_cmake(TargetTypeInvalid)
-run_cmake(TargetTypeStatic)
-
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|LCC|Clang|AppleClang)$")
set (RunCMake_TEST_OPTIONS -DRunCMake_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
@@ -34,41 +41,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
unset (RunCMake_TEST_OPTIONS)
endif()
-if(CMAKE_C_STANDARD_DEFAULT)
- run_cmake(CStandard)
-elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)
- run_cmake(CStandardNoDefault)
-endif()
-if(CMAKE_OBJC_STANDARD_DEFAULT)
- run_cmake(ObjCStandard)
-endif()
-if(CMAKE_CXX_STANDARD_DEFAULT)
- run_cmake(CxxStandard)
-elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
- run_cmake(CxxStandardNoDefault)
-endif()
-if(CMAKE_OBJCXX_STANDARD_DEFAULT)
- run_cmake(ObjCxxStandard)
-endif()
-if(CMake_TEST_CUDA)
- run_cmake(CudaStandard)
-endif()
-if(CMake_TEST_ISPC)
- run_cmake(ISPCTargets)
- run_cmake(ISPCInvalidTarget)
- set(ninja "")
- if(RunCMake_GENERATOR MATCHES "Ninja")
- set(ninja "Ninja")
- endif()
- run_cmake(ISPCDuplicateTarget${ninja})
-endif()
-if((CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC")
- run_cmake(CStandardGNU)
-endif()
-if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC")
- run_cmake(CxxStandardGNU)
-endif()
-
run_cmake(CMP0056)
run_cmake(CMP0066)
run_cmake(CMP0067)
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt
new file mode 100644
index 000000000..53a6d8df6
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceFromBadFile.cmake:[0-9]+ \(try_compile\):
+ SOURCE_FROM_FILE failed to copy "bad#source.c": No such file or directory
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile.cmake b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake
new file mode 100644
index 000000000..0a37f1168
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake
@@ -0,0 +1 @@
+try_compile(RESULT SOURCE_FROM_FILE bad.c "bad#source.c")
diff --git a/Tests/RunCMake/try_compile/SourceFromBadName-result.txt b/Tests/RunCMake/try_compile/SourceFromBadName-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadName-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt b/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt
new file mode 100644
index 000000000..041f3f144
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceFromBadName.cmake:[0-9]+ \(try_compile\):
+ SOURCE_FROM_CONTENT given invalid filename "bad/name.c"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/SourceFromBadName.cmake b/Tests/RunCMake/try_compile/SourceFromBadName.cmake
new file mode 100644
index 000000000..44d92fdd6
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadName.cmake
@@ -0,0 +1 @@
+try_compile(RESULT SOURCE_FROM_CONTENT bad/name.c "int main();")
diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt b/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt b/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt
new file mode 100644
index 000000000..8b2248a7a
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceFromOneArg.cmake:[0-9]+ \(try_compile\):
+ SOURCE_FROM_CONTENT requires exactly two arguments
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg.cmake b/Tests/RunCMake/try_compile/SourceFromOneArg.cmake
new file mode 100644
index 000000000..5a504998e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromOneArg.cmake
@@ -0,0 +1 @@
+try_compile(RESULT SOURCE_FROM_CONTENT test.c)
diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt b/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt b/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt
new file mode 100644
index 000000000..5f2ff618a
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceFromThreeArgs.cmake:[0-9]+ \(try_compile\):
+ SOURCE_FROM_CONTENT requires exactly two arguments
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake b/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake
new file mode 100644
index 000000000..196851aa1
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake
@@ -0,0 +1 @@
+try_compile(RESULT SOURCE_FROM_CONTENT test.c "int" "main();")
diff --git a/Tests/RunCMake/try_compile/TargetTypeExe.cmake b/Tests/RunCMake/try_compile/TargetTypeExe.cmake
index 9b6e7272f..330f5f5d4 100644
--- a/Tests/RunCMake/try_compile/TargetTypeExe.cmake
+++ b/Tests/RunCMake/try_compile/TargetTypeExe.cmake
@@ -1,14 +1,20 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
+
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy
COPY_FILE_ERROR copy_err
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
+
if(copy_err)
message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}")
endif()
diff --git a/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt b/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt
index 08b281a45..e9123e32b 100644
--- a/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt
+++ b/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt
@@ -1,4 +1,4 @@
-^CMake Error at TargetTypeInvalid.cmake:2 \(try_compile\):
+^CMake Error at TargetTypeInvalid.cmake:[0-9]+ \(try_compile\):
Invalid value 'INVALID' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only
'EXECUTABLE' and 'STATIC_LIBRARY' are allowed.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake b/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake
index 0bbc4ac82..15a20bb2d 100644
--- a/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake
+++ b/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake
@@ -1,2 +1,6 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
set(CMAKE_TRY_COMPILE_TARGET_TYPE INVALID)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_compile/TargetTypeStatic.cmake b/Tests/RunCMake/try_compile/TargetTypeStatic.cmake
index 006b8b898..98dea41ef 100644
--- a/Tests/RunCMake/try_compile/TargetTypeStatic.cmake
+++ b/Tests/RunCMake/try_compile/TargetTypeStatic.cmake
@@ -1,14 +1,20 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
enable_language(C)
+
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
-try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/other.c
+
+try_compile(result ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/other.c
OUTPUT_VARIABLE out
COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy
COPY_FILE_ERROR copy_err
)
+
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
+
if(copy_err)
message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}")
endif()
diff --git a/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt
new file mode 100644
index 000000000..2a58e71ac
--- /dev/null
+++ b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
+ Unknown arguments:
+
+ "COMPILE_OUTPUT_VARIABLE"
+ "compOutputVar"
+ "RUN_OUTPUT_VARIABLE"
+ "runOutputVar"
+ "RUN_OUTPUT_STDOUT_VARIABLE"
+ "runOutputStdOutVar"
+ "RUN_OUTPUT_STDERR_VARIABLE"
+ "runOutputStdErrVar"
+ "WORKING_DIRECTORY"
+ "runWorkDir"
+ "ARGS"
+ "runArgs"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/try_compile/TryRunArgs.cmake b/Tests/RunCMake/try_compile/TryRunArgs.cmake
new file mode 100644
index 000000000..e4cb1fe2a
--- /dev/null
+++ b/Tests/RunCMake/try_compile/TryRunArgs.cmake
@@ -0,0 +1,14 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+enable_language(C)
+
+try_compile(RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin"
+ COMPILE_OUTPUT_VARIABLE compOutputVar
+ RUN_OUTPUT_VARIABLE runOutputVar
+ RUN_OUTPUT_STDOUT_VARIABLE runOutputStdOutVar
+ RUN_OUTPUT_STDERR_VARIABLE runOutputStdErrVar
+ WORKING_DIRECTORY runWorkDir
+ ARGS runArgs
+ )
diff --git a/Tests/RunCMake/try_compile/TwoArgs-stderr.txt b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt
index b9c08fc9d..b68e78e37 100644
--- a/Tests/RunCMake/try_compile/TwoArgs-stderr.txt
+++ b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at TwoArgs.cmake:1 \(try_compile\):
- try_compile unknown error.
+CMake Error at TwoArgs.cmake:[0-9]+ \(try_compile\):
+ The try_compile\(\) command requires at least 3 arguments.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt b/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt
new file mode 100644
index 000000000..647499051
--- /dev/null
+++ b/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Debug Log at [^
+]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\):
+ Executing try_compile \(CMAKE_C_ABI_COMPILED\) in:
+
+ [^
+]*/Tests/RunCMake/try_compile/WarnDeprecated-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)
+ WarnDeprecated.cmake:[0-9]+ \(enable_language\)
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/try_compile/new_signature.cmake b/Tests/RunCMake/try_compile/new_signature.cmake
new file mode 100644
index 000000000..cbcb26181
--- /dev/null
+++ b/Tests/RunCMake/try_compile/new_signature.cmake
@@ -0,0 +1,2 @@
+set(try_compile_bindir_or_SOURCES SOURCES)
+set(try_compile_redundant_SOURCES "")
diff --git a/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake
new file mode 100644
index 000000000..ac07ad32e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake
@@ -0,0 +1,66 @@
+# These tests are performed using both the historic and the newer SOURCES
+# signatures of try_compile. It is critical that they behave the same and
+# produce comparable output for both signatures. Tests that cannot do this
+# belong in RunCMakeTests.txt, not here.
+#
+# Tests here MUST include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) and
+# use the variables defined therein appropriately. Refer to existing tests for
+# examples.
+
+run_cmake(CopyFileErrorNoCopyFile)
+run_cmake(NoCopyFile)
+run_cmake(NoCopyFile2)
+run_cmake(NoCopyFileError)
+run_cmake(NoCStandard)
+run_cmake(NoOutputVariable)
+run_cmake(NoOutputVariable2)
+run_cmake(BadLinkLibraries)
+run_cmake(BadSources1)
+run_cmake(BadSources2)
+run_cmake(EmptyValueArgs)
+run_cmake(EmptyListArgs)
+run_cmake(TryRunArgs)
+run_cmake(BuildType)
+run_cmake(BuildTypeAsFlag)
+run_cmake(OutputDirAsFlag)
+
+run_cmake(EnvConfig)
+
+run_cmake(TargetTypeExe)
+run_cmake(TargetTypeInvalid)
+run_cmake(TargetTypeStatic)
+
+if(CMAKE_C_STANDARD_DEFAULT)
+ run_cmake(CStandard)
+elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)
+ run_cmake(CStandardNoDefault)
+endif()
+if(CMAKE_OBJC_STANDARD_DEFAULT)
+ run_cmake(ObjCStandard)
+endif()
+if(CMAKE_CXX_STANDARD_DEFAULT)
+ run_cmake(CxxStandard)
+elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
+ run_cmake(CxxStandardNoDefault)
+endif()
+if(CMAKE_OBJCXX_STANDARD_DEFAULT)
+ run_cmake(ObjCxxStandard)
+endif()
+if(CMake_TEST_CUDA)
+ run_cmake(CudaStandard)
+endif()
+if(CMake_TEST_ISPC)
+ run_cmake(ISPCTargets)
+ run_cmake(ISPCInvalidTarget)
+ set(ninja "")
+ if(RunCMake_GENERATOR MATCHES "Ninja")
+ set(ninja "Ninja")
+ endif()
+ run_cmake(ISPCDuplicateTarget${ninja})
+endif()
+if((CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC")
+ run_cmake(CStandardGNU)
+endif()
+if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC")
+ run_cmake(CxxStandardGNU)
+endif()
diff --git a/Tests/RunCMake/try_compile/old_signature.cmake b/Tests/RunCMake/try_compile/old_signature.cmake
new file mode 100644
index 000000000..94b12dece
--- /dev/null
+++ b/Tests/RunCMake/try_compile/old_signature.cmake
@@ -0,0 +1,2 @@
+set(try_compile_bindir_or_SOURCES ${CMAKE_CURRENT_BINARY_DIR})
+set(try_compile_redundant_SOURCES SOURCES)
diff --git a/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt b/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt
index dcd1bfcbc..f9cc50e3c 100644
--- a/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt
+++ b/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at BadLinkLibraries.cmake:2 \(try_run\):
+CMake Error at BadLinkLibraries.cmake:[0-9+] \(try_run\):
Only libraries may be used as try_compile or try_run IMPORTED
LINK_LIBRARIES. Got not_a_library of type UTILITY.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/try_run/BadLinkLibraries.cmake b/Tests/RunCMake/try_run/BadLinkLibraries.cmake
index a124bf6e1..950a94253 100644
--- a/Tests/RunCMake/try_run/BadLinkLibraries.cmake
+++ b/Tests/RunCMake/try_run/BadLinkLibraries.cmake
@@ -1,4 +1,7 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
add_custom_target(not_a_library)
-try_run(RUN_RESULT COMPILE_RESULT
- ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
LINK_LIBRARIES not_a_library)
diff --git a/Tests/RunCMake/try_run/BinDirEmpty-result.txt b/Tests/RunCMake/try_run/BinDirEmpty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirEmpty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt b/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt
new file mode 100644
index 000000000..def1c22ea
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at BinDirEmpty.cmake:[0-9]+ \(try_run\):
+ No <bindir> specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/BinDirEmpty.cmake b/Tests/RunCMake/try_run/BinDirEmpty.cmake
new file mode 100644
index 000000000..d4b7ee392
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirEmpty.cmake
@@ -0,0 +1 @@
+try_run(runResultVar compileResultVar "" ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_run/BinDirRelative-result.txt b/Tests/RunCMake/try_run/BinDirRelative-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirRelative-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/BinDirRelative-stderr.txt b/Tests/RunCMake/try_run/BinDirRelative-stderr.txt
new file mode 100644
index 000000000..54d4e8666
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirRelative-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at BinDirRelative.cmake:[0-9]+ \(try_run\):
+ <bindir> is not an absolute path:
+
+ 'bin_dir_relative'
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/BinDirRelative.cmake b/Tests/RunCMake/try_run/BinDirRelative.cmake
new file mode 100644
index 000000000..a277403ec
--- /dev/null
+++ b/Tests/RunCMake/try_run/BinDirRelative.cmake
@@ -0,0 +1 @@
+try_run(runResultVar compileResultVar bin_dir_relative ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt b/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt
new file mode 100644
index 000000000..e8baffb12
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoCompileOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "COMPILE_OUTPUT_VARIABLE":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake b/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake
new file mode 100644
index 000000000..9eb7c5e9d
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ COMPILE_OUTPUT_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt b/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoOutputVariable-result.txt b/Tests/RunCMake/try_run/NoOutputVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoOutputVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt
new file mode 100644
index 000000000..46cfca07d
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoOutputVariable.cmake b/Tests/RunCMake/try_run/NoOutputVariable.cmake
new file mode 100644
index 000000000..1901b30bf
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoOutputVariable.cmake
@@ -0,0 +1,4 @@
+try_run(RUN_RESULT COMPILE_RESULT
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ OUTPUT_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt b/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt
new file mode 100644
index 000000000..8ccbdab16
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoRunOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "RUN_OUTPUT_VARIABLE":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable.cmake b/Tests/RunCMake/try_run/NoRunOutputVariable.cmake
new file mode 100644
index 000000000..f9e5e0bc9
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunOutputVariable.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ RUN_OUTPUT_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt b/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt
new file mode 100644
index 000000000..1443ab2eb
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoRunStdErrVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "RUN_OUTPUT_STDERR_VARIABLE":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake b/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake
new file mode 100644
index 000000000..888bc25ef
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake
@@ -0,0 +1,7 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
+ RUN_OUTPUT_STDERR_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt b/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt
new file mode 100644
index 000000000..8b90e9453
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoRunStdOutVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "RUN_OUTPUT_STDOUT_VARIABLE":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake b/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake
new file mode 100644
index 000000000..ed6ab8878
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake
@@ -0,0 +1,7 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
+ RUN_OUTPUT_STDOUT_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt b/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt
new file mode 100644
index 000000000..b6e258f8e
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at NoWorkingDirectory.cmake:[0-9]+ \(try_run\):
+ Error after keyword "WORKING_DIRECTORY":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory.cmake b/Tests/RunCMake/try_run/NoWorkingDirectory.cmake
new file mode 100644
index 000000000..0d6818205
--- /dev/null
+++ b/Tests/RunCMake/try_run/NoWorkingDirectory.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ WORKING_DIRECTORY
+ )
diff --git a/Tests/RunCMake/try_run/RunCMakeTest.cmake b/Tests/RunCMake/try_run/RunCMakeTest.cmake
index d74add05c..dbea089e4 100644
--- a/Tests/RunCMake/try_run/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_run/RunCMakeTest.cmake
@@ -1,6 +1,16 @@
include(RunCMake)
-run_cmake(BadLinkLibraries)
+run_cmake(BinDirEmpty)
+run_cmake(BinDirRelative)
+run_cmake(NoOutputVariable)
+
+set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=old_signature.cmake)
+include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
+unset(RunCMake_TEST_OPTIONS)
+
+set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=new_signature.cmake)
+include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
+unset(RunCMake_TEST_OPTIONS)
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|LCC|Clang|AppleClang)$")
@@ -8,5 +18,3 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
run_cmake(LinkOptions)
unset (RunCMake_TEST_OPTIONS)
endif()
-
-run_cmake(WorkingDirArg)
diff --git a/Tests/RunCMake/try_run/WorkingDirArg.cmake b/Tests/RunCMake/try_run/WorkingDirArg.cmake
index b58382333..375a7033d 100644
--- a/Tests/RunCMake/try_run/WorkingDirArg.cmake
+++ b/Tests/RunCMake/try_run/WorkingDirArg.cmake
@@ -1,6 +1,8 @@
-try_run(RUN_RESULT COMPILE_RESULT
- ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
- RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE
+include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS})
+
+try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
)
diff --git a/Tests/RunCMake/try_run/new_signature.cmake b/Tests/RunCMake/try_run/new_signature.cmake
new file mode 100644
index 000000000..cbcb26181
--- /dev/null
+++ b/Tests/RunCMake/try_run/new_signature.cmake
@@ -0,0 +1,2 @@
+set(try_compile_bindir_or_SOURCES SOURCES)
+set(try_compile_redundant_SOURCES "")
diff --git a/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake
new file mode 100644
index 000000000..e1c1784b7
--- /dev/null
+++ b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake
@@ -0,0 +1,20 @@
+# These tests are performed using both the historic and the newer SOURCES
+# signatures of try_run. It is critical that they behave the same and produce
+# comparable output for both signatures. Tests that cannot do this belong in
+# RunCMakeTests.txt, not here.
+#
+# Tests here MUST include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) and
+# use the variables defined therein appropriately. Refer to existing tests for
+# examples.
+
+run_cmake(BadLinkLibraries)
+run_cmake(BinDirEmpty)
+run_cmake(BinDirRelative)
+
+run_cmake(WorkingDirArg)
+
+run_cmake(NoCompileOutputVariable)
+run_cmake(NoRunOutputVariable)
+run_cmake(NoRunStdOutVariable)
+run_cmake(NoRunStdErrVariable)
+run_cmake(NoWorkingDirectory)
diff --git a/Tests/RunCMake/try_run/old_signature.cmake b/Tests/RunCMake/try_run/old_signature.cmake
new file mode 100644
index 000000000..94b12dece
--- /dev/null
+++ b/Tests/RunCMake/try_run/old_signature.cmake
@@ -0,0 +1,2 @@
+set(try_compile_bindir_or_SOURCES ${CMAKE_CURRENT_BINARY_DIR})
+set(try_compile_redundant_SOURCES SOURCES)
diff --git a/Tests/SwiftMix/CMain.c b/Tests/SwiftMix/CMain.c
index 519058efe..b274322c8 100644
--- a/Tests/SwiftMix/CMain.c
+++ b/Tests/SwiftMix/CMain.c
@@ -1,3 +1,16 @@
+#if !defined(FOO)
+# error "FOO not defined"
+#endif
+#if BAR != 3
+# error "FOO not defined to 3"
+#endif
+#if CCOND != 2
+# error "CCOND not defined to 2"
+#endif
+#if defined(SWIFTCOND)
+# error "SWIFTCOND defined"
+#endif
+
extern int ObjCMain(void);
int main(void)
{
diff --git a/Tests/SwiftMix/CMakeLists.txt b/Tests/SwiftMix/CMakeLists.txt
index 6d8e48bd0..e8b65213f 100644
--- a/Tests/SwiftMix/CMakeLists.txt
+++ b/Tests/SwiftMix/CMakeLists.txt
@@ -4,3 +4,4 @@ project(SwiftMix C Swift)
add_executable(SwiftMix CMain.c ObjCMain.m SwiftMain.swift ObjC-Swift.h)
set_property(TARGET SwiftMix PROPERTY XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "ObjC-Swift.h")
target_compile_options(SwiftMix PRIVATE "$<$<COMPILE_LANGUAGE:C>:-Werror=objc-method-access>")
+target_compile_definitions(SwiftMix PRIVATE "$<IF:$<COMPILE_LANGUAGE:Swift>,SWIFTCOND,CCOND=2>" FOO BAR=3)
diff --git a/Tests/SwiftMix/SwiftMain.swift b/Tests/SwiftMix/SwiftMain.swift
index d9c8cd756..238059d72 100644
--- a/Tests/SwiftMix/SwiftMain.swift
+++ b/Tests/SwiftMix/SwiftMain.swift
@@ -3,6 +3,26 @@ import Foundation
@objc class SwiftMainClass : NSObject {
@objc class func SwiftMain() -> Int32 {
dump("Hello World!");
+#if FOO
+ dump("FOO defined");
+#else
+ fatalError("FOO not defined");
+#endif
+#if BAR
+ dump("BAR defined");
+#else
+ fatalError("BAR not defined");
+#endif
+#if CCOND
+ fatalError("CCOND defined");
+#else
+ dump("CCOND not defined");
+#endif
+#if SWIFTCOND
+ dump("SWIFTCOND defined");
+#else
+ fatalError("SWIFTCOND not defined");
+#endif
return 0;
}
}
diff --git a/Tests/SwiftMixLib/CMakeLists.txt b/Tests/SwiftMixLib/CMakeLists.txt
new file mode 100644
index 000000000..40d3498d5
--- /dev/null
+++ b/Tests/SwiftMixLib/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.24)
+project(SwiftMixLib C CXX Swift)
+
+add_library(SwiftMixedLib lib.c lib.cpp lib.swift)
+add_executable(Swifty main.swift)
+target_link_libraries(Swifty PUBLIC SwiftMixedLib)
diff --git a/Tests/SwiftMixLib/lib.c b/Tests/SwiftMixLib/lib.c
new file mode 100644
index 000000000..8eca51246
--- /dev/null
+++ b/Tests/SwiftMixLib/lib.c
@@ -0,0 +1,4 @@
+int add_int(int a, int b)
+{
+ return a + b;
+}
diff --git a/Tests/SwiftMixLib/lib.cpp b/Tests/SwiftMixLib/lib.cpp
new file mode 100644
index 000000000..3e156b80b
--- /dev/null
+++ b/Tests/SwiftMixLib/lib.cpp
@@ -0,0 +1,4 @@
+int add(int a, int b)
+{
+ return a + b;
+}
diff --git a/Tests/SwiftMixLib/lib.swift b/Tests/SwiftMixLib/lib.swift
new file mode 100644
index 000000000..61009d876
--- /dev/null
+++ b/Tests/SwiftMixLib/lib.swift
@@ -0,0 +1,3 @@
+public func add(a: Int, b: Int) -> Int {
+ a + b
+}
diff --git a/Tests/SwiftMixLib/main.swift b/Tests/SwiftMixLib/main.swift
new file mode 100644
index 000000000..d2e93645d
--- /dev/null
+++ b/Tests/SwiftMixLib/main.swift
@@ -0,0 +1,3 @@
+import SwiftMixedLib
+
+print(add(a: 1, b: 2))
diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt
index 01c2222dc..fa8687d5d 100644
--- a/Tests/SwiftOnly/CMakeLists.txt
+++ b/Tests/SwiftOnly/CMakeLists.txt
@@ -22,9 +22,13 @@ elseif(NOT XCODE_VERSION VERSION_LESS 8.0)
set(CMAKE_Swift_LANGUAGE_VERSION 3.0)
endif()
+add_subdirectory(SubA)
+add_subdirectory(SubB)
+
set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
add_executable(SwiftOnly main.swift)
+target_compile_definitions(SwiftOnly PRIVATE SWIFTONLY)
add_library(L L.swift)
diff --git a/Tests/SwiftOnly/SubA/CMakeLists.txt b/Tests/SwiftOnly/SubA/CMakeLists.txt
new file mode 100644
index 000000000..edebc1697
--- /dev/null
+++ b/Tests/SwiftOnly/SubA/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(SubA SubA.swift)
+target_include_directories(SubA INTERFACE "$<TARGET_FILE_DIR:SubA>")
diff --git a/Tests/SwiftOnly/SubA/SubA.swift b/Tests/SwiftOnly/SubA/SubA.swift
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/SwiftOnly/SubA/SubA.swift
diff --git a/Tests/SwiftOnly/SubB/CMakeLists.txt b/Tests/SwiftOnly/SubB/CMakeLists.txt
new file mode 100644
index 000000000..6e929270f
--- /dev/null
+++ b/Tests/SwiftOnly/SubB/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(SubB SubB.swift)
+target_link_libraries(SubB PRIVATE SubA)
diff --git a/Tests/SwiftOnly/SubB/SubB.swift b/Tests/SwiftOnly/SubB/SubB.swift
new file mode 100644
index 000000000..d593c4cd3
--- /dev/null
+++ b/Tests/SwiftOnly/SubB/SubB.swift
@@ -0,0 +1 @@
+import SubA
diff --git a/Tests/SwiftOnly/main.swift b/Tests/SwiftOnly/main.swift
index 28560d076..a3f1a2c1d 100644
--- a/Tests/SwiftOnly/main.swift
+++ b/Tests/SwiftOnly/main.swift
@@ -1 +1,7 @@
dump("SwiftOnly")
+
+#if SWIFTONLY
+dump("SWIFTONLY defined")
+#else
+fatalError("SWIFTONLY NOT defined")
+#endif
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 000fd2cbc..3e46ed501 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -4,163 +4,96 @@ if(POLICY CMP0129)
endif()
project(TryCompile)
-macro(TEST_ASSERT value msg)
- if (NOT ${value})
- message (SEND_ERROR "Assertion failure:" ${msg} )
- endif ()
+macro(EXPECT_PASS var out)
+ if(NOT ${var})
+ message(SEND_ERROR "Should pass failed:\n${out}")
+ endif()
endmacro()
-macro(TEST_FAIL value msg)
- if (${value})
- message (SEND_ERROR "Failing test succeeded:" ${msg} )
- endif ()
+macro(EXPECT_FAIL var out)
+ if(${var})
+ message(SEND_ERROR "Should fail passed:\n${out}")
+ endif()
endmacro()
-macro(TEST_EXPECT_EXACT command expected)
- if(NOT "x${result}" STREQUAL "x${expected}")
- message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"")
+macro(EXPECT_COMPILED name var out)
+ if(NOT ${var})
+ message(SEND_ERROR "${name} failed compiling:\n${out}")
endif()
endmacro()
-macro(TEST_EXPECT_CONTAINS command expected)
- if(NOT "${result}" MATCHES "${expected}")
- message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"")
+macro(EXPECT_RUN_RESULT name var expected)
+ if(NOT ${var} EQUAL ${expected})
+ message(SEND_ERROR " ${name} gave unexpected run result: ${${var}} expected: ${expected}")
endif()
endmacro()
+macro(TEST_ASSERT value msg)
+ if (NOT ${value})
+ message (SEND_ERROR "Assertion failure:" ${msg} )
+ endif ()
+endmacro()
-# try to compile a file that should compile
-# also check that COPY_FILE works
-try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/pass.c
- OUTPUT_VARIABLE TRY_OUT
- COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfPass
- )
-
-if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
-endif()
-if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfPass")
- message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfPass\" failed")
-else()
- file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass")
-endif()
-
-# try to compile a file that should compile
-# also check that COPY_FILE_ERROR works
-file(WRITE ${TryCompile_BINARY_DIR}/invalid "")
-try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/pass.c
- OUTPUT_VARIABLE TRY_OUT
- COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path
- COPY_FILE_ERROR _captured
- )
-if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
-endif()
-if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path")
- message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message")
-endif()
-
-# try to compile a file that should not compile
-try_compile(SHOULD_FAIL
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/fail.c
- OUTPUT_VARIABLE TRY_OUT)
-if(SHOULD_FAIL)
- message(SEND_ERROR "Should fail passed ${TRY_OUT}")
-endif()
-
-# try to compile a file that should compile
-try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/pass.c
- OUTPUT_VARIABLE TRY_OUT)
-if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
-endif()
-
-# try to compile a file that should not compile
-try_compile(SHOULD_FAIL
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/fail.c
- OUTPUT_VARIABLE TRY_OUT)
-if(SHOULD_FAIL)
- message(SEND_ERROR "Should fail passed ${TRY_OUT}")
-endif()
-
-# try to compile two files that should compile
-try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- SOURCES ${TryCompile_SOURCE_DIR}/pass2a.c ${TryCompile_SOURCE_DIR}/pass2b.cxx
- OUTPUT_VARIABLE TRY_OUT)
-if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
-endif()
-
-# try to compile two files that should not compile
-try_compile(SHOULD_FAIL
- ${TryCompile_BINARY_DIR}
- SOURCES ${TryCompile_SOURCE_DIR}/fail2a.c ${TryCompile_SOURCE_DIR}/fail2b.c
- OUTPUT_VARIABLE TRY_OUT)
-if(SHOULD_FAIL)
- message(SEND_ERROR "Should fail passed ${TRY_OUT}")
-endif()
-
-# try to compile a file that should compile
-set(_c_flags "${CMAKE_C_FLAGS}")
-if(WATCOM)
- string(APPEND CMAKE_C_FLAGS " -dTESTDEF")
-else()
- string(APPEND CMAKE_C_FLAGS " \"-DTESTDEF\"")
-endif()
+# run old signature tests
+set(try_compile_bindir_or_SOURCES ${TryCompile_BINARY_DIR})
+set(try_compile_redundant_SOURCES SOURCES)
+set(try_compile_output_vars OUTPUT_VARIABLE TRY_OUT)
+set(try_compile_compile_output_var TRY_OUT)
+set(try_compile_run_output_var TRY_OUT)
+include(old_and_new_signature_tests.cmake)
+
+# run new signature tests
+set(try_compile_bindir_or_SOURCES SOURCES)
+set(try_compile_redundant_SOURCES "")
+set(try_compile_output_vars
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+set(try_compile_compile_output_var COMPILE_OUT)
+set(try_compile_run_output_var RUN_OUTPUT)
+include(old_and_new_signature_tests.cmake)
+
+# try to compile an empty source specified directly
+try_compile(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE
+ SOURCE_FROM_CONTENT empty.c "")
+if(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE)
+ message(SEND_ERROR "Trying to compile an empty source succeeded?")
+endif()
+
+try_compile(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE
+ SOURCE_FROM_VAR empty.c NAME_OF_A_VAR_THAT_IS_NOT_SET)
+if(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE)
+ message(SEND_ERROR "Trying to compile an empty source succeeded?")
+endif()
+
+# try to compile a copied source
try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/testdef.c
- OUTPUT_VARIABLE TRY_OUT)
-if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
-endif()
-set(CMAKE_C_FLAGS "${_c_flags}")
-
-if(NOT SHOULD_FAIL)
- if(SHOULD_PASS)
- message("All Tests passed, ignore all previous output.")
- else()
- message("Test failed")
- endif()
-else()
- message("Test failed")
-endif()
-try_compile(CMAKE_ANSI_FOR_SCOPE
- ${TryCompile_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT)
-if (CMAKE_ANSI_FOR_SCOPE)
- message("Compiler supports ansi for")
-else()
- message("Compiler does not support ansi for scope")
-endif()
+ SOURCE_FROM_FILE pass.c ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_COMPILED("SOURCE_FROM_FILE" SHOULD_PASS "${TRY_OUT}")
-try_compile(CMAKE_ANSI_FOR_SCOPE
- ${TryCompile_BINARY_DIR}
- ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT)
-if (CMAKE_ANSI_FOR_SCOPE)
- message("Compiler supports ansi for")
-else()
- message("Compiler does not support ansi for scope")
-endif()
+# try to run a source specified directly
+set(TRY_RUN_MAIN_CODE
+ "extern int answer(); \n"
+ "int main() { return answer(); }\n")
+set(TRY_RUN_EXT_CODE
+ "int answer() { return 42; }\n")
-message("use the module now")
-include(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake)
-if (CMAKE_ANSI_FOR_SCOPE)
- message("Compiler supports ansi for")
-else()
- message("Compiler does not support ansi for scope")
-endif()
+try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+ SOURCE_FROM_CONTENT main.c "${TRY_RUN_MAIN_CODE}"
+ SOURCE_FROM_CONTENT answer.c "${TRY_RUN_EXT_CODE}"
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT)
+EXPECT_COMPILED("SOURCE_FROM_CONTENT" SHOULD_COMPILE "${COMPILE_OUTPUT}")
+EXPECT_RUN_RESULT("SOURCE_FROM_CONTENT" SHOULD_EXIT_WITH_ERROR 42)
-message("Testing try_compile project mode")
+try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+ SOURCE_FROM_VAR main.c TRY_RUN_MAIN_CODE
+ SOURCE_FROM_VAR answer.c TRY_RUN_EXT_CODE
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT)
+EXPECT_COMPILED("SOURCE_FROM_VAR" SHOULD_COMPILE "${COMPILE_OUTPUT}")
+EXPECT_RUN_RESULT("SOURCE_FROM_VAR" SHOULD_EXIT_WITH_ERROR 42)
+
+# try to compile a project (old signature)
+message("Testing try_compile project mode (old signature)")
try_compile(TEST_INNER
${TryCompile_BINARY_DIR}/CMakeFiles/Inner
${TryCompile_SOURCE_DIR}/Inner
@@ -168,241 +101,17 @@ try_compile(TEST_INNER
OUTPUT_VARIABLE output)
TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}")
-try_compile(COMPILE_DEFINITIONS_LIST_EXPANDED
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/check_a_b.c
- OUTPUT_VARIABLE output
- COMPILE_DEFINITIONS "-DDEF_A;-DDEF_B"
- )
-if(COMPILE_DEFINITIONS_LIST_EXPANDED)
- message(STATUS "COMPILE_DEFINITIONS list expanded correctly")
-else()
- string(REPLACE "\n" "\n " output " ${output}")
- message(SEND_ERROR "COMPILE_DEFINITIONS list did not expand correctly\n${output}")
-endif()
-
-try_compile(SHOULD_FAIL_DUE_TO_BAD_SOURCE
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/pass.c
- OUTPUT_VARIABLE output
- COMPILE_DEFINITIONS "bad#source.c"
- )
-if(SHOULD_FAIL_DUE_TO_BAD_SOURCE AND NOT CMAKE_GENERATOR MATCHES "Watcom WMake|NMake Makefiles")
- string(REPLACE "\n" "\n " output " ${output}")
- message(SEND_ERROR "try_compile with bad#source.c did not fail:\n${output}")
-elseif(NOT output MATCHES [[(bad#source\.c|bad\.c|bad')]])
- string(REPLACE "\n" "\n " output " ${output}")
- message(SEND_ERROR "try_compile with bad#source.c failed without mentioning bad source:\n${output}")
-else()
- message(STATUS "try_compile with bad#source.c correctly failed")
-endif()
+# try to compile a project (new signature)
+message("Testing try_compile project mode (new signature)")
+try_compile(TEST_INNER
+ PROJECT TryCompileInner
+ SOURCE_DIR ${TryCompile_SOURCE_DIR}/Inner
+ TARGET innerexe
+ OUTPUT_VARIABLE output)
+TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}")
add_executable(TryCompile pass.c)
-######################################
-
-# now two tests for try_run()
-
-# try to run a file that should compile and run without error
-# also check that OUTPUT_VARIABLE contains both the compile output
-# and the run output
-try_run(SHOULD_RUN SHOULD_COMPILE
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/exit_success.c
- OUTPUT_VARIABLE TRY_OUT)
-if(NOT SHOULD_COMPILE)
- message(SEND_ERROR "exit_success failed compiling: ${TRY_OUT}")
-endif()
-if(NOT "${SHOULD_RUN}" STREQUAL "0")
- message(SEND_ERROR "exit_success failed running with exit code ${SHOULD_RUN}")
-endif()
-# check the compile output for the filename
-if(NOT "${TRY_OUT}" MATCHES "exit_success")
- message(SEND_ERROR " TRY_OUT didn't contain \"exit_success\": \"${TRY_OUT}\"")
-endif()
-# check the run output
-if(NOT "${TRY_OUT}" MATCHES "hello world")
- message(SEND_ERROR " TRY_OUT didn't contain \"hello world\": \"${TRY_OUT}\"")
-endif()
-
-try_run(ARG_TEST_RUN ARG_TEST_COMPILE
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/expect_arg.c
- OUTPUT_VARIABLE TRY_OUT
- ARGS arg1 arg2)
-if(NOT ARG_TEST_COMPILE)
- message(SEND_ERROR "expect_arg failed compiling: ${TRY_OUT}")
-endif()
-if(NOT "${ARG_TEST_RUN}" STREQUAL "0")
- message(SEND_ERROR "expect_arg failed running with exit code ${ARG_TEST_RUN} ${TRY_OUT}")
-endif()
-
-# try to run a file that should compile and run, but return an error
-try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/exit_with_error.c
- COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
- RUN_OUTPUT_VARIABLE RUN_OUTPUT)
-
-if(NOT SHOULD_COMPILE)
- message(STATUS " exit_with_error failed compiling: ${COMPILE_OUTPUT}")
-endif()
-if("${SHOULD_EXIT_WITH_ERROR}" STREQUAL "0")
- message(SEND_ERROR " exit_with_error passed with exit code ${SHOULD_EXIT_WITH_ERROR}")
-endif()
-
-# check the compile output, it should contain the filename
-if(NOT "${COMPILE_OUTPUT}" MATCHES "exit_with_error")
- message(SEND_ERROR " COMPILE_OUT didn't contain \"exit_with_error\": \"${COMPILE_OUTPUT}\"")
-endif()
-#... but not the run time output
-if("${COMPILE_OUTPUT}" MATCHES "hello world")
- message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"")
-endif()
-# check the run output, it should stdout
-if(NOT "${RUN_OUTPUT}" MATCHES "hello world")
- message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"")
-endif()
-
-#######################################################################
-#
-# also test that the CHECK_C_SOURCE_COMPILES, CHECK_CXX_SOURCE_COMPILES
-# CHECK_C_SOURCE_RUNS and CHECK_CXX_SOURCE_RUNS macros work
-
-include(CheckCSourceCompiles)
-include(CheckCXXSourceCompiles)
-include(CheckCSourceRuns)
-include(CheckCXXSourceRuns)
-
-CHECK_C_SOURCE_COMPILES("I don't build" C_BUILD_SHOULD_FAIL)
-CHECK_C_SOURCE_COMPILES("int main() {return 0;}" C_BUILD_SHOULD_WORK)
-CHECK_C_SOURCE_RUNS("int main() {return 1;}" C_RUN_SHOULD_FAIL)
-CHECK_C_SOURCE_RUNS("int main() {return 0;}" C_RUN_SHOULD_WORK)
-
-TEST_FAIL(C_BUILD_SHOULD_FAIL "CHECK_C_SOURCE_COMPILES() succeeded, but should have failed")
-TEST_ASSERT(C_BUILD_SHOULD_WORK "CHECK_C_SOURCE_COMPILES() failed")
-TEST_FAIL(C_RUN_SHOULD_FAIL "CHECK_C_SOURCE_RUNS() succeeded, but should have failed")
-TEST_ASSERT(C_RUN_SHOULD_WORK "CHECK_C_SOURCE_RUNS() failed")
-
-CHECK_CXX_SOURCE_COMPILES("I don't build" CXX_BUILD_SHOULD_FAIL)
-CHECK_CXX_SOURCE_COMPILES("int main() {return 0;}" CXX_BUILD_SHOULD_WORK)
-CHECK_CXX_SOURCE_COMPILES("void l(char const (&x)[2]){}; int main() { l(\"\\\\n\"); return 0;}"
- CXX_BUILD_SHOULD_WORK_COMPLEX)
-
-CHECK_CXX_SOURCE_RUNS("int main() {return 2;}" CXX_RUN_SHOULD_FAIL)
-CHECK_CXX_SOURCE_RUNS("int main() {return 0;}" CXX_RUN_SHOULD_WORK)
-
-TEST_FAIL(CXX_BUILD_SHOULD_FAIL "CHECK_CXX_SOURCE_COMPILES() succeeded, but should have failed")
-TEST_ASSERT(CXX_BUILD_SHOULD_WORK "CHECK_CXX_SOURCE_COMPILES() failed")
-TEST_ASSERT(CXX_BUILD_SHOULD_WORK_COMPLEX "CHECK_CXX_SOURCE_COMPILES() failed")
-TEST_FAIL(CXX_RUN_SHOULD_FAIL "CHECK_CXX_SOURCE_RUNS() succeeded, but should have failed")
-TEST_ASSERT(CXX_RUN_SHOULD_WORK "CHECK_CXX_SOURCE_RUNS() failed")
-
-foreach(lang C CXX)
- if(NOT CMAKE_${lang}_COMPILER_ID STREQUAL "PathScale")
- set(${lang}_DD --)
- endif()
-endforeach()
-
-unset(C_BOGUS_FLAG CACHE)
-include(CheckCCompilerFlag)
-CHECK_C_COMPILER_FLAG(${C_DD}-_this_is_not_a_flag_ C_BOGUS_FLAG)
-TEST_FAIL(C_BOGUS_FLAG "CHECK_C_COMPILER_FLAG() succeeded, but should have failed")
-unset(C_BOGUS_FLAG CACHE)
-if(DEFINED C_BOGUS_FLAG)
- # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable
- message(SEND_ERROR "CHECK_C_COMPILER_FLAG shouldn't construct C_BOGUS_FLAG as a normal variable")
-endif()
-
-unset(CXX_BOGUS_FLAG CACHE)
-include(CheckCXXCompilerFlag)
-CHECK_CXX_COMPILER_FLAG(${CXX_DD}-_this_is_not_a_flag_ CXX_BOGUS_FLAG)
-TEST_FAIL(CXX_BOGUS_FLAG "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed")
-unset(CXX_BOGUS_FLAG CACHE)
-if(DEFINED CXX_BOGUS_FLAG)
- # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable
- message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG shouldn't construct CXX_BOGUS_FLAG as a normal variable")
-endif()
-
-if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC")
- unset(C_STRICT_PROTOTYPES CACHE)
- CHECK_C_COMPILER_FLAG("-Werror;-Wstrict-prototypes" C_STRICT_PROTOTYPES)
- TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
-endif()
-
-#########################################################################
-#
-# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJCXX_SOURCE_COMPILES
-# CHECK_OBJC_SOURCE_RUNS and CHECK_OBJCXX_SOURCE_RUNS macros work
-
-if (APPLE)
- enable_language(OBJC)
- enable_language(OBJCXX)
-
- include(CheckOBJCSourceCompiles)
- include(CheckOBJCXXSourceCompiles)
- include(CheckOBJCSourceRuns)
- include(CheckOBJCXXSourceRuns)
-
- CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
- CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
-
- TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
- TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
-
- set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
-
- CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
- CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
- CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
- CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
- CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
-
- TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
- TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
- TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
- TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
- TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
-
-
- CHECK_OBJCXX_SOURCE_COMPILES("I don't build in Objective-C++" OBJCXX_BUILD_SHOULD_FAIL)
- CHECK_OBJCXX_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJCXX_BUILD_SHOULD_WORK)
-
- TEST_FAIL(OBJCXX_BUILD_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_COMPILES() succeeded, but should have failed")
- TEST_ASSERT(SIMPLE_OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
-
- CHECK_OBJCXX_SOURCE_COMPILES("#import <Foundation/Foundation.h>\n#include <iostream>\nint main()\n{\nNSObject *foo;\nstd::cout << \"Hello\" << std::endl;\nreturn 0;\n}\n" OBJCXX_BUILD_SHOULD_WORK)
- CHECK_OBJCXX_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJCXX_RUN_SHOULD_FAIL)
- CHECK_OBJCXX_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJCXX_RUN_SHOULD_WORK)
- CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 2;\n}\n" OBJCXX_RUN_SHOULD_FAIL)
- CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 0;\n}\n" OBJCXX_RUN_SHOULD_WORK)
-
- TEST_ASSERT(OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
- TEST_FAIL(SIMPLE_OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURC_RUNS() succeeds, but should have failed")
- TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
- TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed")
- TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
-
- # try to compile a file that should compile
- try_compile(SHOULD_PASS
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/pass.m
- OUTPUT_VARIABLE TRY_OUT)
- if(NOT SHOULD_PASS)
- message(SEND_ERROR "should pass failed ${TRY_OUT}")
- endif()
-
- # try to compile a file that should not compile
- try_compile(SHOULD_FAIL
- ${TryCompile_BINARY_DIR}
- ${TryCompile_SOURCE_DIR}/fail.m
- OUTPUT_VARIABLE TRY_OUT)
- if(SHOULD_FAIL)
- message(SEND_ERROR "Should fail passed ${TRY_OUT}")
- endif()
-
-endif()
-
#######################################################################
#
# also test that the check_prototype_definition macro works
diff --git a/Tests/TryCompile/exit_with_error.c b/Tests/TryCompile/exit_with_error.c
index f3c523d37..dbddcf583 100644
--- a/Tests/TryCompile/exit_with_error.c
+++ b/Tests/TryCompile/exit_with_error.c
@@ -3,5 +3,5 @@
int main()
{
printf("hello world\n");
- return -1;
+ return 1;
}
diff --git a/Tests/TryCompile/old_and_new_signature_tests.cmake b/Tests/TryCompile/old_and_new_signature_tests.cmake
new file mode 100644
index 000000000..1373ad7fd
--- /dev/null
+++ b/Tests/TryCompile/old_and_new_signature_tests.cmake
@@ -0,0 +1,276 @@
+# try to compile a file that should compile
+try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+
+# try to compile a file that should compile
+# also check that COPY_FILE works
+try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE TRY_OUT
+ COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfPass
+ )
+EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+
+if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfPass")
+ message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfPass\" failed")
+else()
+ file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass")
+endif()
+
+# try to compile a file that should compile
+# also check that COPY_FILE_ERROR works
+file(WRITE ${TryCompile_BINARY_DIR}/invalid "")
+try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE TRY_OUT
+ COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path
+ COPY_FILE_ERROR _captured
+ )
+EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+
+if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path")
+ message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message")
+endif()
+
+# try to compile a file that should not compile
+try_compile(SHOULD_FAIL
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/fail.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}")
+
+# try to compile two files that should compile
+try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass2a.c
+ ${TryCompile_SOURCE_DIR}/pass2b.cxx
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+
+# try to compile two files that should not compile
+try_compile(SHOULD_FAIL
+ ${try_compile_bindir_or_SOURCES}
+ ${try_compile_redundant_SOURCES}
+ ${TryCompile_SOURCE_DIR}/fail2a.c
+ ${TryCompile_SOURCE_DIR}/fail2b.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}")
+
+# try to compile a file that should compile
+set(_c_flags "${CMAKE_C_FLAGS}")
+if(WATCOM)
+ string(APPEND CMAKE_C_FLAGS " -dTESTDEF")
+else()
+ string(APPEND CMAKE_C_FLAGS " \"-DTESTDEF\"")
+endif()
+try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/testdef.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+set(CMAKE_C_FLAGS "${_c_flags}")
+
+try_compile(CMAKE_ANSI_FOR_SCOPE
+ ${try_compile_bindir_or_SOURCES}
+ ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT)
+if(CMAKE_ANSI_FOR_SCOPE)
+ message("Compiler supports ansi for")
+else()
+ message("Compiler does not support ansi for scope")
+endif()
+
+message("use the module now")
+include(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake)
+if(CMAKE_ANSI_FOR_SCOPE)
+ message("Compiler supports ansi for")
+else()
+ message("Compiler does not support ansi for scope")
+endif()
+
+# test that COMPILE_DEFINITIONS are correctly expanded
+try_compile(COMPILE_DEFINITIONS_LIST_EXPANDED
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/check_a_b.c
+ OUTPUT_VARIABLE output
+ COMPILE_DEFINITIONS "-DDEF_A;-DDEF_B"
+ )
+if(COMPILE_DEFINITIONS_LIST_EXPANDED)
+ message(STATUS "COMPILE_DEFINITIONS list expanded correctly")
+else()
+ string(REPLACE "\n" "\n " output " ${output}")
+ message(SEND_ERROR "COMPILE_DEFINITIONS list did not expand correctly\n${output}")
+endif()
+
+# try to compile a file that doesn't exist
+try_compile(SHOULD_FAIL_DUE_TO_BAD_SOURCE
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE output
+ COMPILE_DEFINITIONS "bad#source.c"
+ )
+if(SHOULD_FAIL_DUE_TO_BAD_SOURCE AND NOT CMAKE_GENERATOR MATCHES "Watcom WMake|NMake Makefiles")
+ string(REPLACE "\n" "\n " output " ${output}")
+ message(SEND_ERROR "try_compile with bad#source.c did not fail:\n${output}")
+elseif(NOT output MATCHES [[(bad#source\.c|bad\.c|bad[':])]])
+ string(REPLACE "\n" "\n " output " ${output}")
+ message(SEND_ERROR "try_compile with bad#source.c failed without mentioning bad source:\n${output}")
+else()
+ message(STATUS "try_compile with bad#source.c correctly failed")
+endif()
+
+if(APPLE)
+ # try to compile a file that should compile
+ try_compile(SHOULD_PASS
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.m
+ OUTPUT_VARIABLE TRY_OUT)
+ EXPECT_PASS(SHOULD_PASS "${TRY_OUT}")
+
+ # try to compile a file that should not compile
+ try_compile(SHOULD_FAIL
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/fail.m
+ OUTPUT_VARIABLE TRY_OUT)
+ EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}")
+endif()
+
+# check that try_compile honors NO_CACHE
+function(try_compile_scope_test)
+ try_compile(
+ CACHED_RESULT
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c)
+ try_compile(
+ SHOULD_NOT_ESCAPE_SCOPE_RESULT
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/pass.c
+ NO_CACHE)
+endfunction()
+
+try_compile_scope_test()
+
+if(NOT DEFINED CACHE{CACHED_RESULT})
+ message(SEND_ERROR " Result from try_compile was not cached")
+endif()
+if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RESULT)
+ message(SEND_ERROR " Result from try_compile(NO_CACHE) leaked")
+endif()
+
+######################################
+
+# now test try_run()
+
+# try to run a file that should compile and run without error
+# also check that OUTPUT_VARIABLE contains both the compile output
+# and the run output
+try_run(SHOULD_RUN SHOULD_COMPILE
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/exit_success.c
+ ${try_compile_output_vars})
+EXPECT_COMPILED("exit_success" SHOULD_COMPILE "${${try_compile_compile_output_var}}")
+EXPECT_RUN_RESULT("exit_success" SHOULD_RUN 0)
+
+# check the compile output for the filename
+if(NOT "${${try_compile_compile_output_var}}" MATCHES "exit_success")
+ message(SEND_ERROR
+ " ${try_compile_compile_output_var} didn't contain \"exit_success\":"
+ " \"${${try_compile_compile_output_var}}\"")
+endif()
+# check the run output
+if(NOT "${${try_compile_run_output_var}}" MATCHES "hello world")
+ message(SEND_ERROR
+ " ${try_compile_run_output_var} didn't contain \"hello world\":"
+ " \"${${try_compile_run_output_var}}\"")
+endif()
+
+try_run(ARG_TEST_RUN ARG_TEST_COMPILE
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/expect_arg.c
+ COMPILE_OUTPUT_VARIABLE TRY_OUT
+ ARGS arg1 arg2)
+EXPECT_COMPILED("expect_arg" ARG_TEST_COMPILE "${TRY_OUT}")
+EXPECT_RUN_RESULT("expect_arg" ARG_TEST_RUN 0)
+
+# try to run a file that should compile and run, but return an error
+try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/exit_with_error.c
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+EXPECT_COMPILED("exit_with_error" SHOULD_COMPILE "${COMPILE_OUTPUT}")
+EXPECT_RUN_RESULT("exit_with_error" SHOULD_EXIT_WITH_ERROR 1)
+
+# check the compile output, it should contain the filename
+if(NOT "${COMPILE_OUTPUT}" MATCHES "exit_with_error")
+ message(SEND_ERROR " COMPILE_OUT didn't contain \"exit_with_error\": \"${COMPILE_OUTPUT}\"")
+endif()
+#... but not the run time output
+if("${COMPILE_OUTPUT}" MATCHES "hello world")
+ message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"")
+endif()
+# check the run output, it should contain stdout
+if(NOT "${RUN_OUTPUT}" MATCHES "hello world")
+ message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"")
+endif()
+
+# try to run a file and parse stdout and stderr separately
+# also check that COPY_FILE works
+try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/stdout_and_stderr.c
+ COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfRun
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
+ RUN_OUTPUT_STDOUT_VARIABLE RUN_OUTPUT_STDOUT
+ RUN_OUTPUT_STDERR_VARIABLE RUN_OUTPUT_STDERR)
+EXPECT_PASS(SHOULD_COMPILE "${COMPILE_OUTPUT}")
+
+if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfRun")
+ message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfRun\" failed")
+else()
+ file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfRun")
+endif()
+
+# check the run stdout output
+if(NOT "${RUN_OUTPUT_STDOUT}" MATCHES "hello world")
+ message(SEND_ERROR " RUN_OUTPUT_STDOUT didn't contain \"hello world\": \"${RUN_OUTPUT_STDOUT}\"")
+endif()
+# check the run stderr output
+if(NOT "${RUN_OUTPUT_STDERR}" MATCHES "error")
+ message(SEND_ERROR " RUN_OUTPUT_STDERR didn't contain \"error\": \"${RUN_OUTPUT_STDERR}\"")
+endif()
+
+# check that try_run honors NO_CACHE
+function(try_run_scope_test)
+ try_run(
+ CACHED_RUN_RESULT
+ CACHED_COMPILE_RESULT
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/exit_success.c)
+ try_run(
+ SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT
+ SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT
+ ${try_compile_bindir_or_SOURCES}
+ ${TryCompile_SOURCE_DIR}/exit_success.c
+ NO_CACHE)
+endfunction()
+
+try_run_scope_test()
+
+if(NOT DEFINED CACHE{CACHED_COMPILE_RESULT})
+ message(SEND_ERROR " Compile result from try_run was not cached")
+endif()
+if(NOT DEFINED CACHE{CACHED_RUN_RESULT})
+ message(SEND_ERROR " Run result from try_run was not cached")
+endif()
+if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT)
+ message(SEND_ERROR " Compile result from try_run(NO_CACHE) leaked")
+endif()
+if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT)
+ message(SEND_ERROR " Run result from try_run(NO_CACHE) leaked")
+endif()
diff --git a/Tests/TryCompile/stdout_and_stderr.c b/Tests/TryCompile/stdout_and_stderr.c
new file mode 100644
index 000000000..84ded1f79
--- /dev/null
+++ b/Tests/TryCompile/stdout_and_stderr.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main()
+{
+ fputs("error\n", stderr);
+ puts("hello world\n");
+ return 0;
+}
diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt
index 993d0d65f..2b4f4fa9c 100644
--- a/Tests/VSGNUFortran/CMakeLists.txt
+++ b/Tests/VSGNUFortran/CMakeLists.txt
@@ -11,7 +11,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
# to be in the same directory.
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_isMultiConfig)
- foreach(config ${CMAKE_CONFIGURATION_TYPES})
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
string(TOUPPER "${config}" config)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
diff --git a/Tests/VSWinStorePhone/VerifyAppPackage.cmake b/Tests/VSWinStorePhone/VerifyAppPackage.cmake
index f9440d75e..52e8a5474 100644
--- a/Tests/VSWinStorePhone/VerifyAppPackage.cmake
+++ b/Tests/VSWinStorePhone/VerifyAppPackage.cmake
@@ -26,7 +26,7 @@ if(NOT result EQUAL 0)
message(FATAL_ERROR "Listing app package content failed with: ${error}")
endif()
-foreach(app_pkg_item ${EXPECTED_APP_PKG_CONTENT})
+foreach(app_pkg_item IN LISTS EXPECTED_APP_PKG_CONTENT)
string(FIND ${APP_PKG_CONTENT_OUTPUT} ${app_pkg_item} _found)
if(_found EQUAL -1)
message(FATAL_ERROR "Generated app package is missing an expected item: ${app_pkg_item}")
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index b712c2753..bc163500b 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeDeveloperReference_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index b80fc2288..b0ed911bb 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -91,7 +91,7 @@
{ symbol: [ "std::__decay_and_strip<cmFindPackageCommand::PathLabel &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__decay_and_strip<cmGlobalNinjaGenerator::TargetAlias &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__decay_and_strip<__gnu_cxx::__normal_iterator<const cmCTestTestHandler::cmCTestTestProperties *, std::vector<cmCTestTestHandler::cmCTestTestProperties, std::allocator<cmCTestTestHandler::cmCTestTestProperties> > > &>::__type", private, "\"cmConfigure.h\"", public ] },
- { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] },
+ { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__success_type<std::chrono::duration<double, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__success_type<std::chrono::duration<long, std::ratio<1, 1000000000> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
diff --git a/Utilities/Release/WiX/CustomAction/CMakeLists.txt b/Utilities/Release/WiX/CustomAction/CMakeLists.txt
index 9d89dd89a..dd07f9f24 100644
--- a/Utilities/Release/WiX/CustomAction/CMakeLists.txt
+++ b/Utilities/Release/WiX/CustomAction/CMakeLists.txt
@@ -7,6 +7,10 @@ if(MSVC)
"CMAKE_CXX_FLAGS_${CONFIG}"
"${CMAKE_CXX_FLAGS_${CONFIG}}"
)
+ string(REPLACE "-MD" "-MT"
+ "CMAKE_CXX_FLAGS_${CONFIG}"
+ "${CMAKE_CXX_FLAGS_${CONFIG}}"
+ )
endforeach()
endif()
endif()
diff --git a/Utilities/Release/linux/aarch64/Dockerfile b/Utilities/Release/linux/aarch64/Dockerfile
index 9abae2ab6..e232c018f 100644
--- a/Utilities/Release/linux/aarch64/Dockerfile
+++ b/Utilities/Release/linux/aarch64/Dockerfile
@@ -25,7 +25,7 @@ RUN : \
&& nice make -j $(nproc) \
&& if $TEST; then \
# Run tests that require the full build tree.
- bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|CMakeServerLib\.|RunCMake\.ctest_memcheck)'; \
+ bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|RunCMake\.ctest_memcheck)'; \
fi \
&& bin/cpack -G TGZ \
&& bin/cpack -G STGZ \
diff --git a/Utilities/Release/linux/x86_64/Dockerfile b/Utilities/Release/linux/x86_64/Dockerfile
index 8c98d3e4b..736ee26df 100644
--- a/Utilities/Release/linux/x86_64/Dockerfile
+++ b/Utilities/Release/linux/x86_64/Dockerfile
@@ -26,7 +26,7 @@ RUN : \
&& nice make -j $(nproc) \
&& if $TEST; then \
# Run tests that require the full build tree.
- bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|CMakeServerLib\.|RunCMake\.ctest_memcheck)'; \
+ bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|RunCMake\.ctest_memcheck)'; \
fi \
&& bin/cpack -G TGZ \
&& bin/cpack -G STGZ \
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 9715e07a0..5b66d15ee 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_83_1"
+readonly tag="curl-7_86_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-libuv.bash b/Utilities/Scripts/update-libuv.bash
index 6d423a764..280c6843f 100755
--- a/Utilities/Scripts/update-libuv.bash
+++ b/Utilities/Scripts/update-libuv.bash
@@ -8,7 +8,7 @@ readonly name="libuv"
readonly ownership="libuv upstream <libuv@googlegroups.com>"
readonly subtree="Utilities/cmlibuv"
readonly repo="https://github.com/libuv/libuv.git"
-readonly tag="v1.x"
+readonly tag="v1.44.2"
readonly shortlog=false
readonly paths="
LICENSE
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index fbce1c820..886f4e030 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeHelp_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
@@ -118,12 +118,12 @@ if(SPHINX_QTHELP)
COMMAND ${CMAKE_COMMAND} "-DCSS_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/_static"
-P "${CMAKE_CURRENT_SOURCE_DIR}/apply_qthelp_css_workaround.cmake"
# Workaround sphinx configurability:
- # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable
+ # https://github.com/sphinx-doc/sphinx/issues/1448
COMMAND ${CMAKE_COMMAND} "-DQTHELP_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/"
-P "${CMAKE_CURRENT_SOURCE_DIR}/fixup_qthelp_names.cmake"
# Create proper identifiers. Workaround for
- # https://bitbucket.org/birkenfeld/sphinx/issue/1491/qthelp-should-generate-identifiers-for
+ # https://github.com/sphinx-doc/sphinx/issues/1491
COMMAND "${Python_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/create_identifiers.py"
"${CMAKE_CURRENT_BINARY_DIR}/qthelp/"
@@ -161,7 +161,7 @@ endif()
set(doc_format_outputs "")
set(doc_format_last "")
-foreach(format ${doc_formats})
+foreach(format IN LISTS doc_formats)
set(doc_format_output "doc_format_${format}")
set(doc_format_log "build-${format}.log")
if(CMake_SPHINX_CMAKE_ORG)
@@ -219,13 +219,7 @@ endforeach()
add_custom_target(documentation ALL DEPENDS ${doc_format_outputs})
if(CMake_SPHINX_DEPEND_ON_EXECUTABLES)
- foreach(t
- cmake
- ccmake
- cmake-gui
- cpack
- ctest
- )
+ foreach(t IN ITEMS cmake ccmake cmake-gui cpack ctest)
if(TARGET ${t})
# Build documentation after main executables.
add_dependencies(documentation ${t})
@@ -248,7 +242,7 @@ endif()
if(SPHINX_MAN)
file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual
${CMake_SOURCE_DIR}/Help/manual/*.[1-9].rst)
- foreach(m ${man_rst})
+ foreach(m IN LISTS man_rst)
if("x${m}" MATCHES "^x(.+)\\.([1-9])\\.rst$")
set(name "${CMAKE_MATCH_1}")
set(sec "${CMAKE_MATCH_2}")
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index 9215e1498..c7b123350 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -59,12 +59,6 @@ CMakeLexer.tokens["root"] = [
from docutils.parsers.rst import Directive, directives
from docutils.transforms import Transform
-try:
- from docutils.utils.error_reporting import SafeString, ErrorString
-except ImportError:
- # error_reporting was not in utils before version 0.11:
- from docutils.error_reporting import SafeString, ErrorString
-
from docutils import io, nodes
from sphinx.directives import ObjectDescription
@@ -130,13 +124,13 @@ class CMakeModule(Directive):
f = io.FileInput(source_path=path, encoding=encoding,
error_handler=e_handler)
except UnicodeEncodeError as error:
- raise self.severe('Problems with "%s" directive path:\n'
- 'Cannot encode input file path "%s" '
- '(wrong locale?).' %
- (self.name, SafeString(path)))
+ msg = ('Problems with "%s" directive path:\n'
+ 'Cannot encode input file path "%s" '
+ '(wrong locale?).' % (self.name, path))
+ raise self.severe(msg)
except IOError as error:
- raise self.severe('Problems with "%s" directive path:\n%s.' %
- (self.name, ErrorString(error)))
+ msg = 'Problems with "%s" directive path:\n%s.' % (self.name, error)
+ raise self.severe(msg)
raw_lines = f.read().splitlines()
f.close()
rst = None
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index 4539cf96f..324cd92eb 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -34,3 +34,14 @@ div.outdated {
text-align: center;
width: 100%;
}
+
+/* Revert style to the inherited (normal text) for `:guide:` links */
+code.xref.cmake-guide {
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: inherit;
+ padding: inherit;
+}
+code.xref.cmake-guide span.pre {
+ white-space: inherit;
+}
diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake
index c7b3c8a1b..a38c10183 100644
--- a/Utilities/cmThirdPartyChecks.cmake
+++ b/Utilities/cmThirdPartyChecks.cmake
@@ -10,6 +10,7 @@ set(HAVE_CTYPE_H 1)
set(HAVE_LOCALE_H 1)
set(HAVE_MEMMOVE 1)
set(HAVE_SETLOCALE 1)
+set(HAVE_SNPRINTF 1)
set(HAVE_STDDEF_H 1)
set(HAVE_STDIO_H 1)
set(HAVE_STDLIB_H 1)
@@ -76,6 +77,7 @@ if(WIN32)
set(HAVE_FUTIMENS 0)
set(HAVE_FUTIMES 0)
set(HAVE_FUTIMESAT 0)
+ set(HAVE_GETADDRINFO 1)
set(HAVE_GETEUID 0)
set(HAVE_GETGRGID_R 0)
set(HAVE_GETGRNAM_R 0)
@@ -98,6 +100,7 @@ if(WIN32)
set(HAVE_IDN2_H 0)
set(HAVE_IFADDRS_H 0)
set(HAVE_IF_NAMETOINDEX 0)
+ set(HAVE_INET_NTOP 1)
set(HAVE_INTTYPES_H 1)
set(HAVE_IOCTL 0)
set(HAVE_IOCTL_FIONBIO 0)
@@ -169,6 +172,7 @@ if(WIN32)
set(HAVE_SIGNAL_H 1)
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
set(HAVE_SIZEOF_SA_FAMILY_T 0)
+ set(HAVE_SOCKETPAIR 0)
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
set(HAVE_SPAWN_H 0)
set(HAVE_SSL_H 0)
@@ -234,6 +238,10 @@ if(WIN32)
set(HAVE_WORKING_EXT2_IOC_GETFLAGS 0)
set(HAVE_WORKING_FS_IOC_GETFLAGS 0)
+ if(NOT MINGW)
+ set(HAVE_STRTOK_R 0)
+ endif()
+
# Some POSIX headers are available on Windows.
set(HAVE_SYS_TYPES_H 1)
set(HAVE_SYS_UTIME_H 1)
diff --git a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
index 8ccd016a6..b93e7539a 100644
--- a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
+++ b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,5 +18,7 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
@CMAKE_CONFIGURABLE_FILE_CONTENT@
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index e99ea6f64..75215a122 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
include(CheckCSourceCompiles)
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index 42addd718..6a9fdea09 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef TIME_WITH_SYS_TIME
/* Time with sys/time test */
@@ -182,28 +184,6 @@ if (sizeof (bool *) )
#include <float.h>
int main() { return 0; }
#endif
-#ifdef HAVE_GETADDRINFO
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int main(void) {
- struct addrinfo hints, *ai;
- int error;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-#ifndef getaddrinfo
- (void)getaddrinfo;
-#endif
- error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
- if (error) {
- return 1;
- }
- return 0;
-}
-#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
@@ -514,3 +494,39 @@ main() {
return 0;
}
#endif
+#ifdef HAVE_ATOMIC
+/* includes start */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_STDATOMIC_H
+# include <stdatomic.h>
+#endif
+/* includes end */
+
+int
+main() {
+ _Atomic int i = 1;
+ i = 0; // Force an atomic-write operation.
+ return i;
+}
+#endif
+#ifdef HAVE_WIN32_WINNT
+/* includes start */
+#ifdef WIN32
+# include "../lib/setup-win32.h"
+#endif
+/* includes end */
+
+#define enquote(x) #x
+#define expand(x) enquote(x)
+#pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT))
+
+int
+main() {
+ return 0;
+}
+#endif
diff --git a/Utilities/cmcurl/CMake/FindBearSSL.cmake b/Utilities/cmcurl/CMake/FindBearSSL.cmake
index 9455f4ba3..88d5e87ad 100644
--- a/Utilities/cmcurl/CMake/FindBearSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindBearSSL.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
index 0ed08550d..833e1811a 100644
--- a/Utilities/cmcurl/CMake/FindBrotli.cmake
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
include(FindPackageHandleStandardArgs)
diff --git a/Utilities/cmcurl/CMake/FindCARES.cmake b/Utilities/cmcurl/CMake/FindCARES.cmake
index 71806823d..99cf31d91 100644
--- a/Utilities/cmcurl/CMake/FindCARES.cmake
+++ b/Utilities/cmcurl/CMake/FindCARES.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
# - Find c-ares
# Find the c-ares includes and library
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index 4e4747d6c..ec2bd57ba 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
# - Try to find the GSS Kerberos library
# Once done this will define
diff --git a/Utilities/cmcurl/CMake/FindLibPSL.cmake b/Utilities/cmcurl/CMake/FindLibPSL.cmake
new file mode 100644
index 000000000..66abdd79a
--- /dev/null
+++ b/Utilities/cmcurl/CMake/FindLibPSL.cmake
@@ -0,0 +1,45 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+# - Try to find the libpsl library
+# Once done this will define
+#
+# LIBPSL_FOUND - system has the libpsl library
+# LIBPSL_INCLUDE_DIR - the libpsl include directory
+# LIBPSL_LIBRARY - the libpsl library name
+
+find_path(LIBPSL_INCLUDE_DIR libpsl.h)
+
+find_library(LIBPSL_LIBRARY NAMES psl libpsl)
+
+if(LIBPSL_INCLUDE_DIR)
+ file(STRINGS "${LIBPSL_INCLUDE_DIR}/libpsl.h" libpsl_version_str REGEX "^#define[\t ]+PSL_VERSION[\t ]+\"(.*)\"")
+ string(REGEX REPLACE "^.*\"([^\"]+)\"" "\\1" LIBPSL_VERSION "${libpsl_version_str}")
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibPSL
+ REQUIRED_VARS LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR
+ VERSION_VAR LIBPSL_VERSION)
+
+mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY)
diff --git a/Utilities/cmcurl/CMake/FindLibSSH2.cmake b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
index ce46a408b..0ec7f7e3b 100644
--- a/Utilities/cmcurl/CMake/FindLibSSH2.cmake
+++ b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
# - Try to find the libssh2 library
# Once done this will define
diff --git a/Utilities/cmcurl/CMake/FindMSH3.cmake b/Utilities/cmcurl/CMake/FindMSH3.cmake
index 1b8b9d83a..96477e282 100644
--- a/Utilities/cmcurl/CMake/FindMSH3.cmake
+++ b/Utilities/cmcurl/CMake/FindMSH3.cmake
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#[=======================================================================[.rst:
diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
index 7bdb1976d..fcd6717f6 100644
--- a/Utilities/cmcurl/CMake/FindMbedTLS.cmake
+++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
index 8614492b1..6d70c4a04 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
include(FindPackageHandleStandardArgs)
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
index 643b60097..8d8ebc1b1 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#[=======================================================================[.rst:
diff --git a/Utilities/cmcurl/CMake/FindNGTCP2.cmake b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
index 5757009a5..61e54c2d6 100644
--- a/Utilities/cmcurl/CMake/FindNGTCP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#[=======================================================================[.rst:
@@ -69,7 +71,7 @@ endif()
if(NGTCP2_FIND_COMPONENTS)
set(NGTCP2_CRYPTO_BACKEND "")
foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
- if(component MATCHES "^(OpenSSL|GnuTLS)")
+ if(component MATCHES "^(BoringSSL|OpenSSL|GnuTLS)")
if(NGTCP2_CRYPTO_BACKEND)
message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
endif()
diff --git a/Utilities/cmcurl/CMake/FindNSS.cmake b/Utilities/cmcurl/CMake/FindNSS.cmake
index 899c6b075..6742dda83 100644
--- a/Utilities/cmcurl/CMake/FindNSS.cmake
+++ b/Utilities/cmcurl/CMake/FindNSS.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
if(UNIX)
find_package(PkgConfig QUIET)
diff --git a/Utilities/cmcurl/CMake/FindQUICHE.cmake b/Utilities/cmcurl/CMake/FindQUICHE.cmake
index 0247364d4..fc47027d7 100644
--- a/Utilities/cmcurl/CMake/FindQUICHE.cmake
+++ b/Utilities/cmcurl/CMake/FindQUICHE.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#[=======================================================================[.rst:
diff --git a/Utilities/cmcurl/CMake/FindWolfSSL.cmake b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
index 42256b3cd..986f01e00 100644
--- a/Utilities/cmcurl/CMake/FindWolfSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
find_path(WolfSSL_INCLUDE_DIR NAMES wolfssl/ssl.h)
find_library(WolfSSL_LIBRARY NAMES wolfssl)
diff --git a/Utilities/cmcurl/CMake/FindZstd.cmake b/Utilities/cmcurl/CMake/FindZstd.cmake
index eaba39746..2d6540443 100644
--- a/Utilities/cmcurl/CMake/FindZstd.cmake
+++ b/Utilities/cmcurl/CMake/FindZstd.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#[=======================================================================[.rst:
diff --git a/Utilities/cmcurl/CMake/Macros.cmake b/Utilities/cmcurl/CMake/Macros.cmake
index d57dd6ad5..4d7380eb5 100644
--- a/Utilities/cmcurl/CMake/Macros.cmake
+++ b/Utilities/cmcurl/CMake/Macros.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
#File defines convenience macros for available feature testing
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index 0421c1c34..b3031f749 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
include(CheckCSourceCompiles)
# The begin of the sources (macros and includes)
@@ -46,175 +48,6 @@ endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
-if(1) # CMake hard-codes these
- set(RECV_TYPE_ARG1 "curl_socket_t")
- set(RECV_TYPE_ARG2 "char *")
- set(RECV_TYPE_ARG3 "size_t")
- set(RECV_TYPE_ARG4 "int")
- set(RECV_TYPE_RETV "ssize_t")
-else()
-function(curl_cv_func_recv_run_test recv_retv recv_arg1 recv_arg2 recv_arg3 recv_arg4)
- unset(curl_cv_func_recv_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${recv_retv} ${signature_call_conv}
- recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
- int main(void) {
- ${recv_arg1} s=0;
- ${recv_arg2} buf=0;
- ${recv_arg3} len=0;
- ${recv_arg4} flags=0;
- ${recv_retv} res = recv(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_recv_test)
- message(STATUS
- "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
- if(curl_cv_func_recv_test)
- set(curl_cv_func_recv_args
- "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}" PARENT_SCOPE)
- set(RECV_TYPE_ARG1 "${recv_arg1}" PARENT_SCOPE)
- set(RECV_TYPE_ARG2 "${recv_arg2}" PARENT_SCOPE)
- set(RECV_TYPE_ARG3 "${recv_arg3}" PARENT_SCOPE)
- set(RECV_TYPE_ARG4 "${recv_arg4}" PARENT_SCOPE)
- set(RECV_TYPE_RETV "${recv_retv}" PARENT_SCOPE)
- set(HAVE_RECV 1 PARENT_SCOPE)
- set(curl_cv_func_recv_done 1 PARENT_SCOPE)
- endif()
-endfunction()
-
-check_c_source_compiles("${_source_epilogue}
-int main(void) {
- recv(0, 0, 0, 0);
- return 0;
-}" curl_cv_recv)
-if(curl_cv_recv)
- if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL "unknown")
- if(APPLE)
- curl_cv_func_recv_run_test("ssize_t" "int" "void *" "size_t" "int")
- endif()
- foreach(recv_retv "int" "ssize_t" )
- foreach(recv_arg1 "SOCKET" "int" )
- foreach(recv_arg2 "char *" "void *" )
- foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int")
- foreach(recv_arg4 "int" "unsigned int")
- if(NOT curl_cv_func_recv_done)
- curl_cv_func_recv_run_test(${recv_retv} ${recv_arg1} ${recv_arg2} ${recv_arg3} ${recv_arg4})
- endif()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- else()
- string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
- endif()
-
- if(curl_cv_func_recv_args STREQUAL "unknown")
- message(FATAL_ERROR "Cannot find proper types to use for recv args")
- endif()
-else()
- message(FATAL_ERROR "Unable to link function recv")
-endif()
-set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
-endif()
-set(HAVE_RECV 1)
-
-if(1) # CMake hard-codes these
- set(SEND_QUAL_ARG2 " ")
- set(SEND_TYPE_ARG1 "curl_socket_t")
- set(SEND_TYPE_ARG2 "char *")
- set(SEND_TYPE_ARG3 "size_t")
- set(SEND_TYPE_ARG4 "int")
- set(SEND_TYPE_RETV "ssize_t")
-else()
-function(curl_cv_func_send_run_test send_retv send_arg1 send_arg2 send_arg3 send_arg4)
- unset(curl_cv_func_send_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${send_retv} ${signature_call_conv}
- send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
- int main(void) {
- ${send_arg1} s=0;
- ${send_arg2} buf=0;
- ${send_arg3} len=0;
- ${send_arg4} flags=0;
- ${send_retv} res = send(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_send_test)
- message(STATUS
- "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
- if(curl_cv_func_send_test)
- string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
- string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
- set(curl_cv_func_send_args
- "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}" PARENT_SCOPE)
- set(SEND_TYPE_ARG1 "${send_arg1}" PARENT_SCOPE)
- set(SEND_TYPE_ARG2 "${send_arg2}" PARENT_SCOPE)
- set(SEND_TYPE_ARG3 "${send_arg3}" PARENT_SCOPE)
- set(SEND_TYPE_ARG4 "${send_arg4}" PARENT_SCOPE)
- set(SEND_TYPE_RETV "${send_retv}" PARENT_SCOPE)
- set(HAVE_SEND 1 PARENT_SCOPE)
- set(curl_cv_func_send_done 1 PARENT_SCOPE)
- endif()
-endfunction()
-
-check_c_source_compiles("${_source_epilogue}
-int main(void) {
- send(0, 0, 0, 0);
- return 0;
-}" curl_cv_send)
-if(curl_cv_send)
- if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
- if(APPLE)
- curl_cv_func_send_run_test("ssize_t" "int" "const void *" "size_t" "int")
- endif()
- foreach(send_retv "int" "ssize_t" )
- foreach(send_arg1 "SOCKET" "int" "ssize_t" )
- foreach(send_arg2 "const char *" "const void *" "void *" "char *")
- foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int")
- foreach(send_arg4 "int" "unsigned int")
- if(NOT curl_cv_func_send_done)
- curl_cv_func_send_run_test("${send_retv}" "${send_arg1}" "${send_arg2}" "${send_arg3}" "${send_arg4}")
- endif()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- else()
- string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}")
- endif()
-
- if("${curl_cv_func_send_args}" STREQUAL "unknown")
- message(FATAL_ERROR "Cannot find proper types to use for send args")
- endif()
- set(SEND_QUAL_ARG2 "const")
-else()
- message(FATAL_ERROR "Unable to link function send")
-endif()
-set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
-endif()
-set(HAVE_SEND 1)
-
check_c_source_compiles("${_source_epilogue}
int main(void) {
int flag = MSG_NOSIGNAL;
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index dd653daea..9a513bb6c 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,36 +18,26 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
if(NOT UNIX)
if(WIN32)
- set(HAVE_LIBDL 0)
- set(HAVE_LIBUCB 0)
set(HAVE_LIBSOCKET 0)
- set(NOT_NEED_LIBNSL 0)
- set(HAVE_LIBNSL 0)
set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0)
- set(HAVE_DLOPEN 0)
-
- set(HAVE_ALLOCA_H 0)
set(HAVE_ARPA_INET_H 0)
- set(HAVE_DLFCN_H 0)
set(HAVE_FCNTL_H 1)
set(HAVE_INTTYPES_H 0)
set(HAVE_IO_H 1)
- set(HAVE_MALLOC_H 1)
- set(HAVE_MEMORY_H 1)
set(HAVE_NETDB_H 0)
- set(HAVE_NETINET_IF_ETHER_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NET_IF_H 0)
set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1)
set(HAVE_SIGNAL_H 1)
- set(HAVE_SOCKIO_H 0)
set(HAVE_STDINT_H 0)
set(HAVE_STDLIB_H 1)
set(HAVE_STRINGS_H 0)
@@ -64,40 +54,26 @@ if(NOT UNIX)
set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_TIME_H 1)
- set(HAVE_UNISTD_H 0)
set(HAVE_UTIME_H 0)
- set(HAVE_X509_H 0)
- set(HAVE_ZLIB_H 0)
set(HAVE_SOCKET 1)
- set(HAVE_POLL 0)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
- set(HAVE_STRSTR 1)
- set(HAVE_STRTOK_R 0)
- set(HAVE_STRFTIME 1)
- set(HAVE_UNAME 0)
- set(HAVE_STRCASECMP 0)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_GETTIMEOFDAY 0)
- set(HAVE_INET_ADDR 1)
set(HAVE_CLOSESOCKET 1)
- set(HAVE_SETVBUF 0)
set(HAVE_SIGSETJMP 0)
+ set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_GETPASS_R 0)
- set(HAVE_STRLCAT 0)
set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0)
set(HAVE_UTIME 1)
set(HAVE_RAND_EGD 0)
- set(HAVE_RAND_SCREEN 0)
- set(HAVE_RAND_STATUS 0)
set(HAVE_GMTIME_R 0)
- set(HAVE_LOCALTIME_R 0)
+ set(HAVE_GETADDRINFO_THREADSAFE 1)
set(HAVE_GETHOSTBYNAME_R 0)
- set(HAVE_SIGNAL_FUNC 1)
- set(HAVE_SIGNAL_MACRO 0)
+ set(HAVE_SIGNAL 1)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
@@ -109,11 +85,6 @@ if(NOT UNIX)
set(TIME_WITH_SYS_TIME 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
- if(ENABLE_IPV6)
- set(HAVE_GETADDRINFO 1)
- else()
- set(HAVE_GETADDRINFO 0)
- endif()
set(STDC_HEADERS 1)
set(HAVE_SIGACTION 0)
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 8f9b861ba..78bfd6ffe 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
# File containing various utilities
diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
index d9d9c4e3a..2549d41f4 100644
--- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
+++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
diff --git a/Utilities/cmcurl/CMake/curl-config.cmake.in b/Utilities/cmcurl/CMake/curl-config.cmake.in
index 957148ecc..496a92d0e 100644
--- a/Utilities/cmcurl/CMake/curl-config.cmake.in
+++ b/Utilities/cmcurl/CMake/curl-config.cmake.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
@PACKAGE_INIT@
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index f842270bc..de5df3e4e 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -5,6 +5,7 @@ set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries")
set(CURL_USE_BEARSSL OFF)
set(CURL_USE_GSSAPI OFF)
+set(CURL_USE_LIBPSL OFF)
set(CURL_USE_LIBSSH2 OFF)
set(CURL_USE_LIBSSH OFF)
set(CURL_USE_MBEDTLS OFF)
@@ -65,6 +66,15 @@ set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual")
set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup")
set(ENABLE_UNICODE OFF)
set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
+set(ENABLE_WEBSOCKETS OFF)
+set(HAVE_ATOMIC 0)
+set(HAVE_BORINGSSL 0) # we do not need this info
+set(HAVE_MINGW_ORIGINAL 0) # we do not build on original MinGW anyway
+set(HAVE_RECV 1)
+set(HAVE_SEND 1)
+set(HAVE_STDATOMIC_H 0)
+set(HAVE_STRCASECMP 0) # we do not vendor the code that uses this
+set(HAVE_WIN32_WINNT 0) # we do not need this info
set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
set(PICKY_COMPILER OFF CACHE INTERNAL "Enable picky compiler options")
set(USE_LIBIDN2 ON)
@@ -153,6 +163,8 @@ endif()
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
# curl/libcurl CMake script
# by Tetetest and Sukender (Benoit Neil)
@@ -172,6 +184,27 @@ endif()
# To check:
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
+
+# Note: By default this CMake build script detects the version of some
+# dependencies using `check_symbol_exists`. Those checks do not work
+# in the case that both CURL and its dependency are included as
+# sub-projects in a larger build using `FetchContent`. To support
+# that case, additional variables may be defined by the parent
+# project, ideally in the "extra" find package redirect file:
+# https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
+#
+# The following variables are available:
+# HAVE_RAND_EGD: `RAND_egd` present in OpenSSL
+# HAVE_BORINGSSL: OpenSSL is BoringSSL
+# HAVE_PK11_CREATEMANAGEDGENERICOBJECTL: `PK11_CreateManagedGenericObject` present in NSS
+# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL
+# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
+# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd
+#
+# For each of the above variables, if the variable is DEFINED (either
+# to ON or OFF), the symbol detection will be skipped. If the
+# variable is NOT DEFINED, the symbol detection will be performed.
+
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
@@ -200,7 +233,11 @@ endif()
# SET(PACKAGE_STRING "curl-")
# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.se/mail/")
set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
-set(OS "\"${CMAKE_SYSTEM_NAME}\"")
+if(CMAKE_C_COMPILER_TARGET)
+ set(OS "\"${CMAKE_C_COMPILER_TARGET}\"")
+else()
+ set(OS "\"${CMAKE_SYSTEM_NAME}\"")
+endif()
include_directories(${CURL_SOURCE_DIR}/include)
@@ -211,21 +248,13 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
- option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
if(0) # This code not needed for building within CMake.
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
if(CURL_TARGET_WINDOWS_VERSION)
add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
- elseif(ENABLE_INET_PTON)
- # _WIN32_WINNT_VISTA (0x0600)
- add_definitions(-D_WIN32_WINNT=0x0600)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0600")
- else()
- # _WIN32_WINNT_WINXP (0x0501)
- add_definitions(-D_WIN32_WINNT=0x0501)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501")
+ set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
endif()
endif()
if(ENABLE_UNICODE)
@@ -475,19 +504,7 @@ if(ENABLE_THREADED_RESOLVER)
endif()
# Check for all needed libraries
-if(0) # This code not needed for building within CMake.
-check_library_exists_concat("${CMAKE_DL_LIBS}" dlopen HAVE_LIBDL)
-else()
- # Use the cmake-defined dl libs as dl is should not be used
- # on HPUX, but rather dld this avoids a warning
- list(APPEND CURL_LIBS ${CMAKE_DL_LIBS})
-endif()
check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
-check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL)
-
-if(NOT NOT_NEED_LIBNSL)
- check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
-endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
@@ -598,16 +615,12 @@ if(CURL_USE_OPENSSL)
include_directories(${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
- check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
- check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H)
- check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H)
- check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
- check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
- check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H)
- check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H)
- check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
- check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
- check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
+ if(NOT DEFINED HAVE_RAND_EGD)
+ check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
+ endif()
+ if(NOT DEFINED HAVE_BORINGSSL)
+ check_symbol_exists(OPENSSL_IS_BORINGSSL "openssl/base.h" HAVE_BORINGSSL)
+ endif()
# Optionally build with a specific CA cert bundle.
if(CURL_CA_BUNDLE)
@@ -651,11 +664,13 @@ if(CURL_USE_NSS)
list(APPEND CURL_LIBS ${NSS_LIBRARIES})
set(SSL_ENABLED ON)
set(USE_NSS ON)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_LIBRARIES ${NSS_LIBRARIES})
- check_symbol_exists(PK11_CreateManagedGenericObject "pk11pub.h" HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
- cmake_pop_check_state()
+ if(NOT DEFINED HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${NSS_LIBRARIES})
+ check_symbol_exists(PK11_CreateManagedGenericObject "pk11pub.h" HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
+ cmake_pop_check_state()
+ endif()
endif()
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
@@ -667,20 +682,26 @@ endif()
function(CheckQuicSupportInOpenSSL)
# Be sure that the OpenSSL library actually supports QUIC.
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
- set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
- check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
+ set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
+ check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ cmake_pop_check_state()
+ endif()
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
- message(FATAL_ERROR "QUIC support is missing in OpenSSL/boringssl. Try setting -DOPENSSL_ROOT_DIR")
+ message(FATAL_ERROR "QUIC support is missing in OpenSSL/BoringSSL. Try setting -DOPENSSL_ROOT_DIR")
endif()
- cmake_pop_check_state()
endfunction()
option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
if(USE_NGTCP2)
if(USE_OPENSSL)
- find_package(NGTCP2 REQUIRED OpenSSL)
+ if(HAVE_BORINGSSL)
+ find_package(NGTCP2 REQUIRED BoringSSL)
+ else()
+ find_package(NGTCP2 REQUIRED OpenSSL)
+ endif()
CheckQuicSupportInOpenSSL()
elseif(USE_GNUTLS)
# TODO add GnuTLS support as vtls library.
@@ -708,11 +729,13 @@ if(USE_QUICHE)
set(USE_QUICHE ON)
include_directories(${QUICHE_INCLUDE_DIRS})
list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
- set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
- check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
- cmake_pop_check_state()
+ if(NOT DEFINED HAVE_QUICHE_CONN_SET_QLOG_FD)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
+ set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
+ check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
+ cmake_pop_check_state()
+ endif()
endif()
option(USE_MSH3 "Use msquic library for HTTP/3 support" OFF)
@@ -748,7 +771,6 @@ if(NOT CURL_DISABLE_LDAP)
# Now that we know, we're not using windows LDAP...
if(USE_WIN32_LDAP)
check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
- check_include_file_concat("winber.h" HAVE_WINBER_H)
else()
# Check for LDAP
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
@@ -831,34 +853,29 @@ endif()
if(NOT CURL_DISABLE_LDAPS)
check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
- check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H)
endif()
-# Check for idn
+# Check for idn2
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
-set(HAVE_LIBIDN2 OFF)
if(USE_LIBIDN2)
check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+else()
+ set(HAVE_LIBIDN2 OFF)
endif()
if(WIN32)
option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
if(USE_WIN32_IDN)
- list(APPEND CURL_LIBS "Normaliz")
+ list(APPEND CURL_LIBS "normaliz")
set(WANT_IDN_PROTOTYPES ON)
endif()
endif()
-# Check for symbol dlopen (same as HAVE_LIBDL)
-check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
-
-if(0) # This code not needed for building within CMake.
set(HAVE_LIBZ OFF)
-set(HAVE_ZLIB_H OFF)
set(USE_ZLIB OFF)
-optional_dependency(ZLIB)
+#optional_dependency(ZLIB)
+find_package(ZLIB)
if(ZLIB_FOUND)
- set(HAVE_ZLIB_H ON)
set(HAVE_LIBZ ON)
set(USE_ZLIB ON)
@@ -870,19 +887,8 @@ if(ZLIB_FOUND)
else()
list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
include_directories(${ZLIB_INCLUDE_DIRS})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
endif()
- list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
-endif()
-endif()
-
-#-----------------------------------------------------------------------------
-# CMake-specific curl code.
-
-if(CURL_SPECIAL_LIBZ)
- set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}")
- include_directories(${CURL_SPECIAL_LIBZ_INCLUDES})
- set(HAVE_LIBZ 0)
- set(HAVE_ZLIB_H 0)
endif()
option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
@@ -901,11 +907,13 @@ option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
set(HAVE_ZSTD OFF)
if(CURL_ZSTD)
find_package(Zstd REQUIRED)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
- check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
- cmake_pop_check_state()
+ if (NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
+ check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
+ cmake_pop_check_state()
+ endif()
if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
set(HAVE_ZSTD ON)
list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
@@ -913,42 +921,46 @@ if(CURL_ZSTD)
endif()
endif()
+#libpsl
+option(CURL_USE_LIBPSL "Use libPSL" ON)
+mark_as_advanced(CURL_USE_LIBPSL)
+set(USE_LIBPSL OFF)
+
+if(CURL_USE_LIBPSL)
+ find_package(LibPSL)
+ if(LIBPSL_FOUND)
+ list(APPEND CURL_LIBS ${LIBPSL_LIBRARY})
+ list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBPSL_INCLUDE_DIR}")
+ include_directories("${LIBPSL_INCLUDE_DIR}")
+ set(USE_LIBPSL ON)
+ endif()
+endif()
+
#libSSH2
option(CURL_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CURL_USE_LIBSSH2)
set(USE_LIBSSH2 OFF)
-set(HAVE_LIBSSH2 OFF)
-set(HAVE_LIBSSH2_H OFF)
if(CURL_USE_LIBSSH2)
find_package(LibSSH2)
if(LIBSSH2_FOUND)
list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
- set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY})
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
include_directories("${LIBSSH2_INCLUDE_DIR}")
- set(HAVE_LIBSSH2 ON)
set(USE_LIBSSH2 ON)
-
- # find_package has already found the headers
- set(HAVE_LIBSSH2_H ON)
- set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
- set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
- unset(CMAKE_REQUIRED_LIBRARIES)
endif()
endif()
# libssh
option(CURL_USE_LIBSSH "Use libSSH" OFF)
mark_as_advanced(CURL_USE_LIBSSH)
-if(NOT HAVE_LIBSSH2 AND CURL_USE_LIBSSH)
+if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
find_package(libssh CONFIG)
if(libssh_FOUND)
message(STATUS "Found libssh ${libssh_VERSION}")
# Use imported target for include and library paths.
list(APPEND CURL_LIBS ssh)
set(USE_LIBSSH ON)
- set(HAVE_LIBSSH_LIBSSH_H 1)
endif()
endif()
@@ -990,14 +1002,15 @@ if(CURL_USE_GSSAPI)
set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"")
endforeach()
- set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
- set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
- check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ if(NOT DEFINED HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
+ set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
+ check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ unset(CMAKE_REQUIRED_LIBRARIES)
+ endif()
if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
set(HAVE_OLD_GSSMIT ON)
endif()
- unset(CMAKE_REQUIRED_LIBRARIES)
-
endif()
include_directories(${GSS_INCLUDE_DIR})
@@ -1116,7 +1129,6 @@ else()
set(HAVE_WINSOCK2_H 0)
endif()
-check_include_file_concat("stdio.h" HAVE_STDIO_H)
check_include_file_concat("inttypes.h" HAVE_INTTYPES_H)
check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H)
check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H)
@@ -1129,11 +1141,9 @@ check_include_file_concat("sys/sockio.h" HAVE_SYS_SOCKIO_H)
check_include_file_concat("sys/stat.h" HAVE_SYS_STAT_H)
check_include_file_concat("sys/time.h" HAVE_SYS_TIME_H)
check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H)
-check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H)
check_include_file_concat("sys/un.h" HAVE_SYS_UN_H)
check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
-check_include_file_concat("alloca.h" HAVE_ALLOCA_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H)
check_include_file_concat("assert.h" HAVE_ASSERT_H)
@@ -1142,7 +1152,6 @@ check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
-check_include_file_concat("krb.h" HAVE_KRB_H)
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
check_include_file_concat("locale.h" HAVE_LOCALE_H)
check_include_file_concat("net/if.h" HAVE_NET_IF_H)
@@ -1151,15 +1160,14 @@ check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
-check_include_file_concat("pem.h" HAVE_PEM_H)
check_include_file_concat("poll.h" HAVE_POLL_H)
check_include_file_concat("pwd.h" HAVE_PWD_H)
check_include_file_concat("setjmp.h" HAVE_SETJMP_H)
check_include_file_concat("signal.h" HAVE_SIGNAL_H)
check_include_file_concat("ssl.h" HAVE_SSL_H)
+check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H)
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
-check_include_file_concat("stdio.h" HAVE_STDIO_H)
check_include_file_concat("stdlib.h" HAVE_STDLIB_H)
check_include_file_concat("string.h" HAVE_STRING_H)
check_include_file_concat("strings.h" HAVE_STRINGS_H)
@@ -1169,24 +1177,20 @@ check_include_file_concat("termios.h" HAVE_TERMIOS_H)
check_include_file_concat("time.h" HAVE_TIME_H)
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
check_include_file_concat("utime.h" HAVE_UTIME_H)
-check_include_file_concat("x509.h" HAVE_X509_H)
check_include_file_concat("process.h" HAVE_PROCESS_H)
check_include_file_concat("stddef.h" HAVE_STDDEF_H)
-check_include_file_concat("dlfcn.h" HAVE_DLFCN_H)
-check_include_file_concat("malloc.h" HAVE_MALLOC_H)
-check_include_file_concat("memory.h" HAVE_MEMORY_H)
-check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
-check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
check_type_size(size_t SIZEOF_SIZE_T)
check_type_size(ssize_t SIZEOF_SSIZE_T)
check_type_size("time_t" SIZEOF_TIME_T)
-find_file(RANDOM_FILE urandom /dev)
-mark_as_advanced(RANDOM_FILE)
+if(NOT CMAKE_CROSSCOMPILING)
+ find_file(RANDOM_FILE urandom /dev)
+ mark_as_advanced(RANDOM_FILE)
+endif()
# Check for some functions that are used
if(HAVE_LIBWS2_32)
@@ -1197,57 +1201,46 @@ elseif(HAVE_LIBNETWORK)
set(CMAKE_REQUIRED_LIBRARIES network)
endif()
+check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
+check_symbol_exists(socketpair "${CURL_INCLUDES}" HAVE_SOCKETPAIR)
+check_symbol_exists(recv "${CURL_INCLUDES}" HAVE_RECV)
+check_symbol_exists(send "${CURL_INCLUDES}" HAVE_SEND)
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
-check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL)
check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP)
-check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR)
check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R)
-check_symbol_exists(strftime "${CURL_INCLUDES}" HAVE_STRFTIME)
-check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP)
check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP)
check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI)
-check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI)
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
-if(NOT HAVE_STRNCMPI)
- set(HAVE_STRCMPI)
-endif()
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
-check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
-check_symbol_exists(usleep "${CURL_INCLUDES}" HAVE_USLEEP)
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
-check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
-check_symbol_exists(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
-check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
-check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
-if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
- set(HAVE_SIGNAL 1)
-endif()
-check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
+check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL)
check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO)
+if(NOT HAVE_GETADDRINFO)
+ set(HAVE_GETADDRINFO_THREADSAFE OFF)
+endif()
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
-check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME)
check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
@@ -1255,10 +1248,16 @@ check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
-check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
-check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL)
-check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
+
+if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
+ # earlier MSVC compilers had faulty snprintf implementations
+ check_symbol_exists(snprintf "${CURL_INCLUDES}" HAVE_SNPRINTF)
+endif()
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
+check_symbol_exists(inet_ntop "${CURL_INCLUDES}" HAVE_INET_NTOP)
+if(MSVC AND (MSVC_VERSION LESS_EQUAL 1600))
+ set(HAVE_INET_NTOP OFF)
+endif()
check_symbol_exists(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
@@ -1308,7 +1307,6 @@ foreach(CURL_TEST
HAVE_IOCTL_FIONBIO
HAVE_IOCTL_SIOCGIFADDR
HAVE_SETSOCKOPT_SO_NONBLOCK
- HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
TIME_WITH_SYS_TIME
HAVE_O_NONBLOCK
HAVE_GETHOSTBYNAME_R_3
@@ -1320,10 +1318,10 @@ foreach(CURL_TEST
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
- HAVE_GETADDRINFO
HAVE_FILE_OFFSET_BITS
HAVE_VARIADIC_MACROS_C99
HAVE_VARIADIC_MACROS_GCC
+ HAVE_ATOMIC
)
curl_internal_test(${CURL_TEST})
endforeach()
@@ -1340,8 +1338,30 @@ set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
set(CMAKE_EXTRA_INCLUDE_FILES "")
+if(WIN32)
+ # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
+ curl_internal_test(HAVE_WIN32_WINNT)
+ if(HAVE_WIN32_WINNT)
+ string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
+ string(REGEX REPLACE ".*_WIN32_WINNT=" "" HAVE_WIN32_WINNT "${OUTPUT}")
+ message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
+ endif()
+ # avoid storing HAVE_WIN32_WINNT in CMake cache
+ unset(HAVE_WIN32_WINNT CACHE)
+endif()
+
set(CMAKE_REQUIRED_FLAGS)
+option(ENABLE_WEBSOCKETS "Set to ON to enable EXPERIMENTAL websockets" OFF)
+
+if(ENABLE_WEBSOCKETS)
+ if(${SIZEOF_CURL_OFF_T} GREATER "4")
+ set(USE_WEBSOCKETS ON)
+ else()
+ message(WARNING "curl_off_t is too small to enable WebSockets")
+ endif()
+endif()
+
foreach(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
@@ -1385,18 +1405,6 @@ if(NOT HAVE_IN_ADDR_T)
set(in_addr_t "unsigned long")
endif()
-# Fix libz / zlib.h
-
-if(NOT CURL_SPECIAL_LIBZ)
- if(NOT HAVE_LIBZ)
- set(HAVE_ZLIB_H 0)
- endif()
-
- if(NOT HAVE_ZLIB_H)
- set(HAVE_LIBZ 0)
- endif()
-endif()
-
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
if(HAVE_FIONBIO OR
@@ -1456,6 +1464,25 @@ if(WIN32)
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
list(APPEND CURL_LIBS "advapi32" "crypt32")
endif()
+
+ # Matching logic used for Curl_win32_random()
+ if(MINGW)
+ check_c_source_compiles("
+ #include <_mingw.h>
+ #if defined(__MINGW64_VERSION_MAJOR)
+ #error
+ #endif
+ int main(void) {
+ return 0;
+ }"
+ HAVE_MINGW_ORIGINAL)
+ endif()
+
+ if(NOT HAVE_MINGW_ORIGINAL)
+ list(APPEND CURL_LIBS "bcrypt")
+ else()
+ set(HAVE_FTRUNCATE OFF)
+ endif()
endif()
if(MSVC)
@@ -1465,6 +1492,8 @@ if(MSVC)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+ elseif(CMAKE_C_FLAGS MATCHES "-W[0-4]")
+ string(REGEX REPLACE "-W[0-4]" "-W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
endif()
@@ -1611,6 +1640,9 @@ _add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
_add_if("unicode" ENABLE_UNICODE)
+_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND
+ HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
+_add_if("PSL" USE_LIBPSL)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1647,6 +1679,8 @@ _add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
+_add_if("WS" USE_WEBSOCKETS)
+_add_if("WSS" USE_WEBSOCKETS)
if(_items)
list(SORT _items)
endif()
@@ -1780,13 +1814,13 @@ if(MSVC_VERSION EQUAL 1600)
endif()
endif()
-if(NOT TARGET uninstall)
+if(NOT TARGET curl_uninstall)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
IMMEDIATE @ONLY)
- add_custom_target(uninstall
+ add_custom_target(curl_uninstall
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
endif()
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index 8cdfdb69e..7a1258145 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -73,7 +75,8 @@
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
- (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000))
+ (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \
+ defined(__sun__)
#include <sys/select.h>
#endif
@@ -575,7 +578,7 @@ typedef enum {
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
- CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_OBSOLETE75, /* 75 - NOT IN USE since 7.82.0 */
CURLE_OBSOLETE76, /* 76 - NOT IN USE since 7.82.0 */
CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
or wrong format */
@@ -613,6 +616,7 @@ typedef enum {
CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */
CURLE_PROXY, /* 97 - proxy handshake error */
CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */
+ CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */
CURL_LAST /* never use! */
} CURLcode;
@@ -677,6 +681,7 @@ typedef enum {
#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
#define CURLE_LDAP_INVALID_URL CURLE_OBSOLETE62
#define CURLE_CONV_REQD CURLE_OBSOLETE76
+#define CURLE_CONV_FAILED CURLE_OBSOLETE75
/* This was the error code 50 in 7.7.3 and a few earlier versions, this
is no longer used by libcurl but is instead #defined here only to not
@@ -835,8 +840,8 @@ enum curl_khstat {
CURLKHSTAT_FINE_ADD_TO_FILE,
CURLKHSTAT_FINE,
CURLKHSTAT_REJECT, /* reject the connection, return an error */
- CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
- this causes a CURLE_DEFER error but otherwise the
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now.
+ Causes a CURLE_PEER_FAILED_VERIFICATION error but the
connection will be left intact etc */
CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
@@ -855,7 +860,18 @@ typedef int
const struct curl_khkey *knownkey, /* known */
const struct curl_khkey *foundkey, /* found */
enum curl_khmatch, /* libcurl's view on the keys */
- void *clientp); /* custom pointer passed from app */
+ void *clientp); /* custom pointer passed with */
+ /* CURLOPT_SSH_KEYDATA */
+
+typedef int
+ (*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed*/
+ /* with CURLOPT_SSH_HOSTKEYDATA */
+ int keytype, /* CURLKHTYPE */
+ const char *key, /*hostkey to check*/
+ size_t keylen); /*length of the key*/
+ /*return CURLE_OK to accept*/
+ /*or something else to refuse*/
+
/* parameter for the CURLOPT_USE_SSL option */
typedef enum {
@@ -995,7 +1011,8 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
#define CURLHSTS_ENABLE (long)(1<<0)
#define CURLHSTS_READONLYFILE (long)(1<<1)
-/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS
+ options. Do not use. */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
#define CURLPROTO_FTP (1<<2)
@@ -1461,12 +1478,11 @@ typedef enum {
Note that setting multiple bits may cause extra network round-trips. */
CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111),
- /* FTP option that changes the timeout, in seconds, associated with
- getting a response. This is different from transfer timeout time and
- essentially places a demand on the FTP server to acknowledge commands
- in a timely manner. */
- CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112),
-#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+ /* Option that changes the timeout, in seconds, associated with getting a
+ response. This is different from transfer timeout time and essentially
+ places a demand on the server to acknowledge commands in a timely
+ manner. For FTP, SMTP, IMAP and POP3. */
+ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112),
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
tell libcurl to use those IP versions only. This only has effect on
@@ -2122,6 +2138,25 @@ typedef enum {
/* Set MIME option flags. */
CURLOPT(CURLOPT_MIME_OPTIONS, CURLOPTTYPE_LONG, 315),
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CURLOPT(CURLOPT_SSH_HOSTKEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 316),
+
+ /* set the SSH host key callback custom pointer */
+ CURLOPT(CURLOPT_SSH_HOSTKEYDATA, CURLOPTTYPE_CBPOINT, 317),
+
+ /* specify which protocols that are allowed to be used for the transfer,
+ which thus helps the app which takes URLs from users or other external
+ inputs and want to restrict what protocol(s) to deal with. Defaults to
+ all built-in protocols. */
+ CURLOPT(CURLOPT_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 318),
+
+ /* specify which protocols that libcurl is allowed to follow directs to */
+ CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319),
+
+ /* websockets options */
+ CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2147,6 +2182,9 @@ typedef enum {
#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+/* */
+#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT
+
#else
/* This is set if CURL_NO_OLDIES is defined at compile-time */
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
@@ -2161,7 +2199,7 @@ typedef enum {
#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */
#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */
- /* three convenient "aliases" that follow the name scheme better */
+ /* Convenient "aliases" */
#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
@@ -2589,8 +2627,10 @@ CURL_EXTERN void curl_free(void *p);
*
* curl_global_init() should be invoked exactly once for each application that
* uses libcurl and before any call of other libcurl functions.
- *
- * This function is not thread-safe!
+
+ * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the
+ * curl_version_info_data.features flag (fetch by curl_version_info()).
+
*/
CURL_EXTERN CURLcode curl_global_init(long flags);
@@ -2799,8 +2839,9 @@ typedef enum {
CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
CURLINFO_REFERER = CURLINFO_STRING + 60,
-
- CURLINFO_LASTONE = 60
+ CURLINFO_CAINFO = CURLINFO_STRING + 61,
+ CURLINFO_CAPATH = CURLINFO_STRING + 62,
+ CURLINFO_LASTONE = 62
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -3006,6 +3047,7 @@ typedef struct curl_version_info_data curl_version_info_data;
#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */
#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */
#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */
+#define CURL_VERSION_THREADSAFE (1<<30) /* libcurl API is thread-safe */
/*
* NAME curl_version_info()
@@ -3070,6 +3112,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "urlapi.h"
#include "options.h"
#include "header.h"
+#include "websockets.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 718d58c08..9eb50679c 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
@@ -30,13 +32,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.83.1"
+#define LIBCURL_VERSION "7.86.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 83
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 86
+#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x075301
+#define LIBCURL_VERSION_NUM 0x075600
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index 2dbfb26b5..9c7e63ada 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef __cplusplus
extern "C" {
diff --git a/Utilities/cmcurl/include/curl/header.h b/Utilities/cmcurl/include/curl/header.h
index 7715b61e2..1598c6f11 100644
--- a/Utilities/cmcurl/include/curl/header.h
+++ b/Utilities/cmcurl/include/curl/header.h
@@ -20,8 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct curl_header {
char *name; /* this might not use the same case */
char *value;
@@ -61,4 +67,8 @@ CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy,
int request,
struct curl_header *prev);
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
#endif /* CURLINC_HEADER_H */
diff --git a/Utilities/cmcurl/include/curl/mprintf.h b/Utilities/cmcurl/include/curl/mprintf.h
index 3549552db..cb948dcd9 100644
--- a/Utilities/cmcurl/include/curl/mprintf.h
+++ b/Utilities/cmcurl/include/curl/mprintf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <stdarg.h>
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index 91cd95d32..2f3ec37a7 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
This is an "external" header file. Don't give away any internals here!
@@ -75,6 +77,7 @@ typedef enum {
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
CURLM_ABORTED_BY_CALLBACK,
+ CURLM_UNRECOVERABLE_POLL,
CURLM_LAST
} CURLMcode;
@@ -121,7 +124,7 @@ struct curl_waitfd {
/*
* Name: curl_multi_init()
*
- * Desc: inititalize multi-style curl usage
+ * Desc: initialize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
diff --git a/Utilities/cmcurl/include/curl/options.h b/Utilities/cmcurl/include/curl/options.h
index 91360b358..a792687cf 100644
--- a/Utilities/cmcurl/include/curl/options.h
+++ b/Utilities/cmcurl/include/curl/options.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef __cplusplus
@@ -31,7 +33,7 @@ typedef enum {
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
- CURLOT_STRING, /* (char * to zero terminated buffer) */
+ CURLOT_STRING, /* (char * to null-terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
diff --git a/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h
index 60596c756..82e1b5fef 100644
--- a/Utilities/cmcurl/include/curl/stdcheaders.h
+++ b/Utilities/cmcurl/include/curl/stdcheaders.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <sys/types.h>
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index 000fea6c7..8d56b8a4a 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 9e14d8a37..2dabcb416 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* wraps curl_easy_setopt() with typechecking */
@@ -270,9 +272,9 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
- (option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
@@ -286,10 +288,8 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \
+ (option) == CURLOPT_PROTOCOLS_STR || \
(option) == CURLOPT_PROXY || \
- (option) == CURLOPT_PROXYPASSWORD || \
- (option) == CURLOPT_PROXYUSERNAME || \
- (option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
@@ -297,17 +297,21 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
+ (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
- (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_REDIR_PROTOCOLS_STR || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
@@ -374,6 +378,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_TRAILERDATA || \
+ (option) == CURLOPT_SSH_HOSTKEYDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
index a475f91b6..e15c213cc 100644
--- a/Utilities/cmcurl/include/curl/urlapi.h
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl.h"
diff --git a/Utilities/cmcurl/include/curl/websockets.h b/Utilities/cmcurl/include/curl/websockets.h
new file mode 100644
index 000000000..4d57f91e5
--- /dev/null
+++ b/Utilities/cmcurl/include/curl/websockets.h
@@ -0,0 +1,83 @@
+#ifndef CURLINC_WEBSOCKETS_H
+#define CURLINC_WEBSOCKETS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct curl_ws_frame {
+ int age; /* zero */
+ int flags; /* See the CURLWS_* defines */
+ curl_off_t offset; /* the offset of this data into the frame */
+ curl_off_t bytesleft; /* number of pending bytes left of the payload */
+};
+
+/* flag bits */
+#define CURLWS_TEXT (1<<0)
+#define CURLWS_BINARY (1<<1)
+#define CURLWS_CONT (1<<2)
+#define CURLWS_CLOSE (1<<3)
+#define CURLWS_PING (1<<4)
+#define CURLWS_OFFSET (1<<5)
+
+/*
+ * NAME curl_ws_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the websocket connection. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *recv,
+ struct curl_ws_frame **metap);
+
+/* sendflags for curl_ws_send() */
+#define CURLWS_PONG (1<<6)
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the websocket connection. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t framesize,
+ unsigned int sendflags);
+
+/* bits for the CURLOPT_WS_OPTIONS bitmask: */
+#define CURLWS_RAW_MODE (1<<0)
+
+CURL_EXTERN struct curl_ws_frame *curl_ws_meta(CURL *curl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CURLINC_WEBSOCKETS_H */
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 6cf45adc3..313847397 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,9 +18,12 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
set(LIB_NAME cmcurl)
set(LIBCURL_OUTPUT_NAME cmcurl)
+add_definitions(-DBUILDING_LIBCURL)
if(BUILD_SHARED_LIBS)
set(CURL_STATICLIB NO)
@@ -143,7 +146,6 @@ endif()
if(WIN32)
if(BUILD_SHARED_LIBS)
- set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "_USRDLL")
if(MSVC)
# Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib"
@@ -156,16 +158,18 @@ target_include_directories(${LIB_NAME} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
-install(TARGETS ${LIB_NAME}
- EXPORT ${TARGETS_EXPORT_NAME}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-)
-
-export(TARGETS ${LIB_NAME}
- APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
- NAMESPACE ${PROJECT_NAME}::
-)
+if(CURL_ENABLE_EXPORT_TARGET)
+ install(TARGETS ${LIB_NAME}
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
+
+ export(TARGETS ${LIB_NAME}
+ FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
+ NAMESPACE ${PROJECT_NAME}::
+ )
+endif()
endif()
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 1ab007896..b2d2e9e52 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -18,6 +18,8 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
+# SPDX-License-Identifier: curl
+#
###########################################################################
LIB_VAUTH_CFILES = \
@@ -108,7 +110,6 @@ LIB_CFILES = \
content_encoding.c \
cookie.c \
curl_addrinfo.c \
- curl_ctype.c \
curl_des.c \
curl_endian.c \
curl_fnmatch.c \
@@ -127,7 +128,6 @@ LIB_CFILES = \
curl_threads.c \
dict.c \
doh.c \
- dotdot.c \
dynbuf.c \
easy.c \
easygetopt.c \
@@ -135,6 +135,7 @@ LIB_CFILES = \
escape.c \
file.c \
fileinfo.c \
+ fopen.c \
formdata.c \
ftp.c \
ftplistparser.c \
@@ -176,6 +177,7 @@ LIB_CFILES = \
multi.c \
netrc.c \
nonblock.c \
+ noproxy.c \
openldap.c \
parsedate.c \
pingpong.c \
@@ -215,7 +217,8 @@ LIB_CFILES = \
version.c \
version_win32.c \
warnless.c \
- wildcard.c
+ wildcard.c \
+ ws.c
LIB_HFILES = \
altsvc.h \
@@ -260,14 +263,16 @@ LIB_HFILES = \
curlx.h \
dict.h \
doh.h \
- dotdot.h \
dynbuf.h \
+ easy_lock.h \
easyif.h \
easyoptions.h \
escape.h \
file.h \
fileinfo.h \
+ fopen.h \
formdata.h \
+ functypes.h \
ftp.h \
ftplistparser.h \
getinfo.h \
@@ -297,6 +302,7 @@ LIB_HFILES = \
multiif.h \
netrc.h \
nonblock.h \
+ noproxy.h \
parsedate.h \
pingpong.h \
pop3.h \
@@ -336,7 +342,8 @@ LIB_HFILES = \
urldata.h \
version_win32.h \
warnless.h \
- wildcard.h
+ wildcard.h \
+ ws.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index dd2d0ebed..7bca84015 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
* The Alt-Svc: header is defined in RFC 7838:
@@ -34,7 +36,7 @@
#include "parsedate.h"
#include "sendf.h"
#include "warnless.h"
-#include "rand.h"
+#include "fopen.h"
#include "rename.h"
/* The last 3 #include files should be in this order */
@@ -50,15 +52,7 @@
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10
-#if defined(USE_QUICHE) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_MSH3) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#else
#define H3VERSION "h3"
-#endif
static enum alpnid alpn2alpnid(char *name)
{
@@ -184,10 +178,9 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
/*
* Load alt-svc entries from the given file. The text based line-oriented file
- * format is documented here:
- * https://github.com/curl/curl/wiki/QUIC-implementation
+ * format is documented here: https://curl.se/docs/alt-svc.html
*
- * This function only returns error on major problems that prevents alt-svc
+ * This function only returns error on major problems that prevent alt-svc
* handling to work completely. It will ignore individual syntactical errors
* etc.
*/
@@ -336,8 +329,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
- char *tempstore;
- unsigned char randsuffix[9];
+ char *tempstore = NULL;
if(!altsvc)
/* no cache activated */
@@ -351,17 +343,8 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
/* marked as read-only, no file or zero length file name */
return CURLE_OK;
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return CURLE_FAILED_INIT;
-
- tempstore = aprintf("%s.%s.tmp", file, randsuffix);
- if(!tempstore)
- return CURLE_OUT_OF_MEMORY;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
- result = CURLE_WRITE_ERROR;
- else {
+ result = Curl_fopen(data, file, &out, &tempstore);
+ if(!result) {
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
@@ -373,10 +356,10 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
break;
}
fclose(out);
- if(!result && Curl_rename(tempstore, file))
+ if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
- if(result)
+ if(result && tempstore)
unlink(tempstore);
}
free(tempstore);
@@ -479,6 +462,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+ size_t entries = 0;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -489,11 +473,10 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
DEBUGASSERT(asi);
- /* Flush all cached alternatives for this source origin, if any */
- altsvc_flush(asi, srcalpnid, srchost, srcport);
-
/* "clear" is a magic keyword */
if(strcasecompare(alpnbuf, "clear")) {
+ /* Flush cached alternatives for this source origin */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK;
}
@@ -511,6 +494,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
+ bool valid = TRUE;
p++;
if(*p != ':') {
/* host name starts here */
@@ -520,7 +504,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
len = p - hostp;
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc host name, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
else {
memcpy(namebuf, hostp, len);
@@ -537,10 +521,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
unsigned long port = strtoul(++p, &end_ptr, 10);
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
+ else
+ dstport = curlx_ultous(port);
p = end_ptr;
- dstport = curlx_ultous(port);
}
if(*p++ != '\"')
break;
@@ -592,7 +577,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
persist = TRUE;
}
}
- if(dstalpnid) {
+ if(dstalpnid && valid) {
+ if(!entries++)
+ /* Flush cached alternatives for this source origin, if any - when
+ this is the first entry of the line. */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
+
as = altsvc_createid(srchost, dsthost,
srcalpnid, dstalpnid,
srcport, dstport);
@@ -606,10 +596,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
Curl_alpnid2str(dstalpnid));
}
}
- else {
- infof(data, "Unknown alt-svc protocol \"%s\", skipping.",
- alpnbuf);
- }
}
else
break;
diff --git a/Utilities/cmcurl/lib/altsvc.h b/Utilities/cmcurl/lib/altsvc.h
index 2ab89e705..2751d272a 100644
--- a/Utilities/cmcurl/lib/altsvc.h
+++ b/Utilities/cmcurl/lib/altsvc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index 78bb22c7e..e8c2fc02e 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,13 +18,23 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifdef __AMIGA__
-# include "amigaos.h"
-# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+
+#include <curl/curl.h>
+
+#include "hostip.h"
+#include "amigaos.h"
+
+#ifdef HAVE_PROTO_BSDSOCKET_H
+# if defined(__amigaos4__)
+# include <bsdsocket/socketbasetags.h>
+# elif !defined(USE_AMISSL)
# include <amitcp/socketbasetags.h>
# endif
# ifdef __libnix__
@@ -36,8 +46,154 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __AMIGA__
-#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#ifdef HAVE_PROTO_BSDSOCKET_H
+
+#ifdef __amigaos4__
+/*
+ * AmigaOS 4.x specific code
+ */
+
+/*
+ * hostip4.c - Curl_ipv4_resolve_r() replacement code
+ *
+ * Logic that needs to be considered are the following build cases:
+ * - newlib networking
+ * - clib2 networking
+ * - direct bsdsocket.library networking (usually AmiSSL builds)
+ * Each with the threaded resolver enabled or not.
+ *
+ * With the threaded resolver enabled, try to use gethostbyname_r() where
+ * available, otherwise (re)open bsdsocket.library and fallback to
+ * gethostbyname().
+ */
+
+#include <proto/bsdsocket.h>
+
+static struct SocketIFace *__CurlISocket = NULL;
+static uint32 SocketFeatures = 0;
+
+#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
+#define HAVE_BSDSOCKET_GETADDRINFO 0x02
+
+CURLcode Curl_amiga_init(void)
+{
+ struct SocketIFace *ISocket;
+ struct Library *base = OpenLibrary("bsdsocket.library", 4);
+
+ if(base) {
+ ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+ if(ISocket) {
+ ULONG enabled = 0;
+
+ SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE,
+ SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled,
+ TAG_DONE);
+
+ if(enabled) {
+ SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R;
+ }
+
+ __CurlISocket = ISocket;
+
+ atexit(Curl_amiga_cleanup);
+
+ return CURLE_OK;
+ }
+ CloseLibrary(base);
+ }
+
+ return CURLE_FAILED_INIT;
+}
+
+void Curl_amiga_cleanup(void)
+{
+ if(__CurlISocket) {
+ struct Library *base = __CurlISocket->Data.LibBase;
+ DropInterface((struct Interface *)__CurlISocket);
+ CloseLibrary(base);
+ __CurlISocket = NULL;
+ }
+}
+
+#ifdef CURLRES_AMIGA
+/*
+ * Because we need to handle the different cases in hostip4.c at run-time,
+ * not at compile-time, based on what was detected in Curl_amiga_init(),
+ * we replace it completely with our own as to not complicate the baseline
+ * code. Assumes malloc/calloc/free are thread safe because Curl_he2ai()
+ * allocates memory also.
+ */
+
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+ int port)
+{
+ struct Curl_addrinfo *ai = NULL;
+ struct hostent *h;
+ struct SocketIFace *ISocket = __CurlISocket;
+
+ if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) {
+ LONG h_errnop = 0;
+ struct hostent *buf;
+
+ buf = calloc(1, CURL_HOSTENT_SIZE);
+ if(buf) {
+ h = gethostbyname_r((STRPTR)hostname, buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h_errnop);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ free(buf);
+ }
+ }
+ else {
+ #ifdef CURLRES_THREADED
+ /* gethostbyname() is not thread safe, so we need to reopen bsdsocket
+ * on the thread's context
+ */
+ struct Library *base = OpenLibrary("bsdsocket.library", 4);
+ if(base) {
+ ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+ if(ISocket) {
+ h = gethostbyname((STRPTR)hostname);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ DropInterface((struct Interface *)ISocket);
+ }
+ CloseLibrary(base);
+ }
+ #else
+ /* not using threaded resolver - safe to use this as-is */
+ h = gethostbyname(hostname);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ #endif
+ }
+
+ return ai;
+}
+#endif /* CURLRES_AMIGA */
+
+#ifdef USE_AMISSL
+int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *errorfds, struct timeval *timeout)
+{
+ int r = WaitSelect(nfds, readfds, writefds, errorfds, timeout, 0);
+ /* Ensure Ctrl-C signal is actioned */
+ if((r == -1) && (SOCKERRNO == EINTR))
+ raise(SIGINT);
+ return r;
+}
+#endif /* USE_AMISSL */
+
+#elif !defined(USE_AMISSL) /* __amigaos4__ */
+/*
+ * Amiga OS3 specific code
+ */
+
struct Library *SocketBase = NULL;
extern int errno, h_errno;
@@ -47,7 +203,7 @@ void __request(const char *msg);
# define __request(msg) Printf(msg "\n\a")
#endif
-void Curl_amiga_cleanup()
+void Curl_amiga_cleanup(void)
{
if(SocketBase) {
CloseLibrary(SocketBase);
@@ -55,68 +211,36 @@ void Curl_amiga_cleanup()
}
}
-bool Curl_amiga_init()
+CURLcode Curl_amiga_init(void)
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
__request("No TCP/IP Stack running!");
- return FALSE;
+ return CURLE_FAILED_INIT;
}
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
- return FALSE;
+ return CURLE_FAILED_INIT;
}
#ifndef __libnix__
atexit(Curl_amiga_cleanup);
#endif
- return TRUE;
+ return CURLE_OK;
}
#ifdef __libnix__
ADD2EXIT(Curl_amiga_cleanup, -50);
#endif
-#endif /* HAVE_PROTO_BSDSOCKET_H */
+#endif /* !USE_AMISSL */
-#ifdef USE_AMISSL
-void Curl_amiga_X509_free(X509 *a)
-{
- X509_free(a);
-}
-
-/* AmiSSL replaces many functions with macros. Curl requires pointer
- * to some of these functions. Thus, we have to encapsulate these macros.
- */
-
-#include "warnless.h"
-
-int (SHA256_Init)(SHA256_CTX *c)
-{
- return SHA256_Init(c);
-};
-
-int (SHA256_Update)(SHA256_CTX *c, const void *data, size_t len)
-{
- return SHA256_Update(c, data, curlx_uztoui(len));
-};
-
-int (SHA256_Final)(unsigned char *md, SHA256_CTX *c)
-{
- return SHA256_Final(md, c);
-};
-
-void (X509_INFO_free)(X509_INFO *a)
-{
- X509_INFO_free(a);
-};
+#endif /* HAVE_PROTO_BSDSOCKET_H */
-#endif /* USE_AMISSL */
#endif /* __AMIGA__ */
-
diff --git a/Utilities/cmcurl/lib/amigaos.h b/Utilities/cmcurl/lib/amigaos.h
index 02e5bb546..9abfb59ea 100644
--- a/Utilities/cmcurl/lib/amigaos.h
+++ b/Utilities/cmcurl/lib/amigaos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,25 +20,23 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
-#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
+#if defined(__AMIGA__) && defined(HAVE_PROTO_BSDSOCKET_H) && \
+ (!defined(USE_AMISSL) || defined(__amigaos4__))
-bool Curl_amiga_init();
-void Curl_amiga_cleanup();
+CURLcode Curl_amiga_init(void);
+void Curl_amiga_cleanup(void);
#else
-#define Curl_amiga_init() 1
+#define Curl_amiga_init() CURLE_OK
#define Curl_amiga_cleanup() Curl_nop_stmt
#endif
-#ifdef USE_AMISSL
-#include <openssl/x509v3.h>
-void Curl_amiga_X509_free(X509 *a);
-#endif /* USE_AMISSL */
-
#endif /* HEADER_CURL_AMIGAOS_H */
diff --git a/Utilities/cmcurl/lib/arpa_telnet.h b/Utilities/cmcurl/lib/arpa_telnet.h
index cbe31de5a..523f7f51e 100644
--- a/Utilities/cmcurl/lib/arpa_telnet.h
+++ b/Utilities/cmcurl/lib/arpa_telnet.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_TELNET
/*
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index c885adef5..33edba139 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -113,6 +115,7 @@ struct thread_data {
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
+ char hostname[1];
};
/* How long we are willing to wait for additional parallel responses after
@@ -250,8 +253,6 @@ void Curl_resolver_kill(struct Curl_easy *data)
*/
static void destroy_async_data(struct Curl_async *async)
{
- free(async->hostname);
-
if(async->tdata) {
struct thread_data *res = async->tdata;
if(res) {
@@ -263,8 +264,6 @@ static void destroy_async_data(struct Curl_async *async)
}
async->tdata = NULL;
}
-
- async->hostname = NULL;
}
/*
@@ -306,7 +305,7 @@ int Curl_resolver_getsock(struct Curl_easy *data,
* 2) wait for the timeout period to check for action on ares' sockets.
* 3) tell ares to act on all the sockets marked as "with action"
*
- * return number of sockets it worked on
+ * return number of sockets it worked on, or -1 on error
*/
static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
@@ -338,8 +337,11 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
break;
}
- if(num)
+ if(num) {
nfds = Curl_poll(pfd, num, timeout_ms);
+ if(nfds < 0)
+ return -1;
+ }
else
nfds = 0;
@@ -376,7 +378,8 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
DEBUGASSERT(dns);
*dns = NULL;
- waitperform(data, 0);
+ if(waitperform(data, 0) < 0)
+ return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
/* Now that we've checked for any last minute results above, see if there are
@@ -475,7 +478,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
else
timeout_ms = 1000;
- waitperform(data, timeout_ms);
+ if(waitperform(data, timeout_ms) < 0)
+ return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
if(result || data->state.async.done)
@@ -742,7 +746,7 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
* Curl_resolver_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
@@ -751,25 +755,18 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int port,
int *waitp)
{
- char *bufp;
-
+ struct thread_data *res = NULL;
+ size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
- bufp = strdup(hostname);
- if(bufp) {
- struct thread_data *res = NULL;
- free(data->state.async.hostname);
- data->state.async.hostname = bufp;
+ res = calloc(sizeof(struct thread_data) + namelen, 1);
+ if(res) {
+ strcpy(res->hostname, hostname);
+ data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.status = 0; /* clear */
data->state.async.dns = NULL; /* clear */
- res = calloc(sizeof(struct thread_data), 1);
- if(!res) {
- free(data->state.async.hostname);
- data->state.async.hostname = NULL;
- return NULL;
- }
data->state.async.tdata = res;
/* initial status - failed */
@@ -782,13 +779,17 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
+ /* Since the service is a numerical one, set the hint flags
+ * accordingly to save a call to getservbyname in inside C-Ares
+ */
+ hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
@@ -797,7 +798,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
#else
#ifdef HAVE_CARES_IPV6
- if(Curl_ipv6works(data)) {
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 149172ad3..8b375eb5e 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -262,23 +264,28 @@ int init_thread_sync_data(struct thread_data *td,
return 1;
err_exit:
- /* Memory allocation failed */
+#ifndef CURL_DISABLE_SOCKETPAIR
+ if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
+ sclose(tsd->sock_pair[0]);
+ tsd->sock_pair[0] = CURL_SOCKET_BAD;
+ }
+#endif
destroy_thread_sync_data(tsd);
return 0;
}
-static int getaddrinfo_complete(struct Curl_easy *data)
+static CURLcode getaddrinfo_complete(struct Curl_easy *data)
{
struct thread_sync_data *tsd = conn_thread_sync_data(data);
- int rc;
+ CURLcode result;
- rc = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
+ result = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
tsd->res = NULL;
- return rc;
+ return result;
}
@@ -700,7 +707,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
diff --git a/Utilities/cmcurl/lib/asyn.h b/Utilities/cmcurl/lib/asyn.h
index 313039582..1aab21aaa 100644
--- a/Utilities/cmcurl/lib/asyn.h
+++ b/Utilities/cmcurl/lib/asyn.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -146,7 +148,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
* Curl_resolver_getaddrinfo() - when using this resolver
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*
diff --git a/Utilities/cmcurl/lib/base64.c b/Utilities/cmcurl/lib/base64.c
index 960a1ca3a..52654c2bc 100644
--- a/Utilities/cmcurl/lib/base64.c
+++ b/Utilities/cmcurl/lib/base64.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* Base64 encoding/decoding */
@@ -41,10 +43,11 @@
#include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
+/* Padding character string starts at offset 64. */
static const char base64[]=
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
+/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */
static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
@@ -52,25 +55,18 @@ static const char base64url[]=
static size_t decodeQuantum(unsigned char *dest, const char *src)
{
size_t padding = 0;
- const char *s, *p;
+ const char *s;
unsigned long i, x = 0;
for(i = 0, s = src; i < 4; i++, s++) {
if(*s == '=') {
- x = (x << 6);
+ x <<= 6;
padding++;
}
else {
- unsigned long v = 0;
- p = base64;
-
- while(*p && (*p != *s)) {
- v++;
- p++;
- }
-
- if(*p == *s)
- x = (x << 6) + v;
+ const char *p = strchr(base64, *s);
+ if(p)
+ x = (x << 6) + curlx_uztoul(p - base64);
else
return 0;
}
@@ -107,11 +103,11 @@ CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen)
{
size_t srclen = 0;
- size_t length = 0;
size_t padding = 0;
size_t i;
size_t numQuantums;
size_t rawlen = 0;
+ const char *padptr;
unsigned char *pos;
unsigned char *newstr;
@@ -124,19 +120,17 @@ CURLcode Curl_base64_decode(const char *src,
return CURLE_BAD_CONTENT_ENCODING;
/* Find the position of any = padding characters */
- while((src[length] != '=') && src[length])
- length++;
-
- /* A maximum of two = padding characters is allowed */
- if(src[length] == '=') {
+ padptr = strchr(src, '=');
+ if(padptr) {
padding++;
- if(src[length + 1] == '=')
+ /* A maximum of two = padding characters is allowed */
+ if(padptr[1] == '=')
padding++;
- }
- /* Check the = padding characters weren't part way through the input */
- if(length + padding != srclen)
- return CURLE_BAD_CONTENT_ENCODING;
+ /* Check the = padding characters weren't part way through the input */
+ if(padptr + padding != src + srclen)
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
/* Calculate the number of quantums */
numQuantums = srclen / 4;
@@ -144,7 +138,7 @@ CURLcode Curl_base64_decode(const char *src,
/* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding;
- /* Allocate our buffer including room for a zero terminator */
+ /* Allocate our buffer including room for a null-terminator */
newstr = malloc(rawlen + 1);
if(!newstr)
return CURLE_OUT_OF_MEMORY;
@@ -185,6 +179,7 @@ static CURLcode base64_encode(const char *table64,
char *output;
char *base64data;
const char *indata = inputbuff;
+ const char *padstr = &table64[64]; /* Point to padding string. */
*outptr = NULL;
*outlen = 0;
@@ -222,27 +217,30 @@ static CURLcode base64_encode(const char *table64,
switch(inputparts) {
case 1: /* only one byte read */
- msnprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
+ i = msnprintf(output, 5, "%c%c%s%s",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ padstr,
+ padstr);
break;
case 2: /* two bytes read */
- msnprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
+ i = msnprintf(output, 5, "%c%c%c%s",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ padstr);
break;
default:
- msnprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]]);
+ i = msnprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]]);
break;
}
- output += 4;
+ output += i;
}
/* Zero terminate */
@@ -270,8 +268,6 @@ static CURLcode base64_encode(const char *table64,
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
- * When encoded data length is 0, returns NULL in *outptr.
- *
* @unittest: 1302
*/
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
@@ -293,8 +289,6 @@ CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
- * When encoded data length is 0, returns NULL in *outptr.
- *
* @unittest: 1302
*/
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
diff --git a/Utilities/cmcurl/lib/bufref.c b/Utilities/cmcurl/lib/bufref.c
index b84511e18..91b037431 100644
--- a/Utilities/cmcurl/lib/bufref.c
+++ b/Utilities/cmcurl/lib/bufref.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/bufref.h b/Utilities/cmcurl/lib/bufref.h
index 25f65d894..96b818b53 100644
--- a/Utilities/cmcurl/lib/bufref.h
+++ b/Utilities/cmcurl/lib/bufref.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
index 69082982c..86abcdb0f 100644
--- a/Utilities/cmcurl/lib/c-hyper.c
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -52,6 +54,7 @@
#include "multiif.h"
#include "progress.h"
#include "content_encoding.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -288,7 +291,7 @@ static CURLcode status_line(struct Curl_easy *data,
len);
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
- writetype = CLIENTWRITE_HEADER;
+ writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(data, writetype,
@@ -469,6 +472,24 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
if(result)
break;
+ k->deductheadercount =
+ (100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
+#ifdef USE_WEBSOCKETS
+ if(k->upgr101 == UPGR101_WS) {
+ if(http_status == 101) {
+ /* verify the response */
+ result = Curl_ws_accept(data);
+ if(result)
+ return result;
+ }
+ else {
+ failf(data, "Expected 101, got %u", k->httpcode);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ break;
+ }
+ }
+#endif
+
/* Curl_http_auth_act() checks what authentication methods that are
* available and decides which one (if any) to use. It will set 'newurl'
* if an auth method was picked. */
@@ -690,9 +711,18 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
data->state.hresult = result;
return HYPER_POLL_ERROR;
}
- if(!fillcount)
- /* done! */
- *chunk = NULL;
+ if(!fillcount) {
+ if((data->req.keepon & KEEP_SEND_PAUSE) != KEEP_SEND_PAUSE)
+ /* done! */
+ *chunk = NULL;
+ else {
+ /* paused, save a waker */
+ if(data->hyp.send_body_waker)
+ hyper_waker_free(data->hyp.send_body_waker);
+ data->hyp.send_body_waker = hyper_context_waker(ctx);
+ return HYPER_POLL_PENDING;
+ }
+ }
else {
hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
if(copy)
@@ -907,12 +937,13 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- if(conn->negnpn == CURL_HTTP_VERSION_2) {
+ if(conn->alpn == CURL_HTTP_VERSION_2) {
hyper_clientconn_options_http2(options, 1);
h2 = TRUE;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
+ hyper_clientconn_options_http1_allow_multiline_headers(options, 1);
hyper_clientconn_options_exec(options, h->exec);
@@ -1002,10 +1033,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* For HTTP/2, we show the Host: header as if we sent it, to make it look
like for HTTP/1 but it isn't actually sent since :authority is then
used. */
- result = Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
- strlen(data->state.aptr.host));
- if(result)
- goto error;
+ Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
+ strlen(data->state.aptr.host));
}
if(data->state.aptr.proxyuserpwd) {
@@ -1047,6 +1076,21 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
+#ifndef CURL_DISABLE_ALTSVC
+ if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
+ char *altused = aprintf("Alt-Used: %s:%d\r\n",
+ conn->conn_to_host.name, conn->conn_to_port);
+ if(!altused) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ result = Curl_hyper_header(data, headers, altused);
+ if(result)
+ goto error;
+ free(altused);
+ }
+#endif
+
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
!Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
@@ -1098,6 +1142,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, headers);
+
result = Curl_add_timecondition(data, headers);
if(result)
goto error;
@@ -1110,9 +1157,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
- result = Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
- if(result)
- goto error;
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
data->req.upload_chunky = FALSE;
sendtask = hyper_clientconn_send(client, req);
diff --git a/Utilities/cmcurl/lib/c-hyper.h b/Utilities/cmcurl/lib/c-hyper.h
index d63defeff..70507ad2a 100644
--- a/Utilities/cmcurl/lib/c-hyper.h
+++ b/Utilities/cmcurl/lib/c-hyper.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -34,6 +36,7 @@ struct hyptransfer {
const hyper_executor *exec;
hyper_task *endtask;
hyper_waker *exp100_waker;
+ hyper_waker *send_body_waker;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index aa29620fa..a557ac6dc 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -496,7 +498,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->bits.close &&
- !conn->bits.connect_only) {
+ !conn->connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index ef11dcfd2..94664bc35 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -29,6 +31,7 @@
* be shared.
*/
+#include <curl/curl.h>
#include "timeval.h"
struct connectdata;
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 9bcf525eb..ac007c61b 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -470,8 +472,10 @@ static CURLcode bindlocal(struct Curl_easy *data,
}
if(--portnum > 0) {
- infof(data, "Bind to local port %hu failed, trying next", port);
port++; /* try next port */
+ if(port == 0)
+ break;
+ infof(data, "Bind to local port %hu failed, trying next", port - 1);
/* We re-use/clobber the port variable here below */
if(sock->sa_family == AF_INET)
si4->sin_port = ntohs(port);
@@ -621,7 +625,8 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
else
data->info.conn_local_ip[0] = 0;
data->info.conn_scheme = conn->handler->scheme;
- data->info.conn_protocol = conn->handler->protocol;
+ /* conn_protocol can only provide "old" protocols */
+ data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
data->info.conn_primary_port = conn->port;
data->info.conn_remote_port = conn->remote_port;
data->info.conn_local_port = local_port;
@@ -757,11 +762,10 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
char local_ip[MAX_IPADR_LEN] = "";
int local_port = -1;
- if(conn->transport == TRNSPRT_TCP) {
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen)
- Curl_conninfo_remote(data, conn, sockfd);
- Curl_conninfo_local(data, sockfd, local_ip, &local_port);
- } /* end of TCP-only section */
+ if(!conn->bits.reuse &&
+ (conn->transport != TRNSPRT_TCP || !conn->bits.tcp_fastopen))
+ Curl_conninfo_remote(data, conn, sockfd);
+ Curl_conninfo_local(data, sockfd, local_ip, &local_port);
/* persist connection info in session handle */
Curl_persistconninfo(data, conn, local_ip, local_port);
@@ -899,6 +903,8 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->tempsock[i] = CURL_SOCKET_BAD;
post_SOCKS(data, conn, sockindex, connected);
connkeep(conn, "HTTP/3 default");
+ if(conn->tempsock[other] != CURL_SOCKET_BAD)
+ Curl_quic_disconnect(data, conn, other);
return CURLE_OK;
}
/* When a QUIC connect attempt fails, the better error explanation is in
@@ -1033,7 +1039,6 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
(conn->tempsock[1] == CURL_SOCKET_BAD)) {
/* no more addresses to try */
const char *hostname;
- char buffer[STRERROR_LEN];
CURLcode failreason = result;
/* if the first address family runs out of addresses to try before the
@@ -1060,11 +1065,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
"%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
hostname, conn->port,
Curl_timediff(now, data->progress.t_startsingle),
-#ifdef ENABLE_QUIC
- (conn->transport == TRNSPRT_QUIC) ?
- curl_easy_strerror(result) :
-#endif
- Curl_strerror(error, buffer, sizeof(buffer)));
+ curl_easy_strerror(result));
Curl_quic_disconnect(data, conn, 0);
Curl_quic_disconnect(data, conn, 1);
@@ -1196,6 +1197,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
#ifdef TCP_FASTOPEN_CONNECT
int optval = 1;
#endif
+ const char *ipmsg;
char buffer[STRERROR_LEN];
curl_socket_t *sockp = &conn->tempsock[tempindex];
*sockp = CURL_SOCKET_BAD;
@@ -1213,7 +1215,13 @@ static CURLcode singleipconnect(struct Curl_easy *data,
Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
- infof(data, " Trying %s:%d...", ipaddress, port);
+#ifdef ENABLE_IPV6
+ if(addr.family == AF_INET6)
+ ipmsg = " Trying [%s]:%d...";
+ else
+#endif
+ ipmsg = " Trying %s:%d...";
+ infof(data, ipmsg, ipaddress, port);
#ifdef ENABLE_IPV6
is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1600,9 +1608,20 @@ CURLcode Curl_socket(struct Curl_easy *data,
*/
addr->family = ai->ai_family;
- addr->socktype = (conn->transport == TRNSPRT_TCP) ? SOCK_STREAM : SOCK_DGRAM;
- addr->protocol = conn->transport != TRNSPRT_TCP ? IPPROTO_UDP :
- ai->ai_protocol;
+ switch(conn->transport) {
+ case TRNSPRT_TCP:
+ addr->socktype = SOCK_STREAM;
+ addr->protocol = IPPROTO_TCP;
+ break;
+ case TRNSPRT_UNIX:
+ addr->socktype = SOCK_STREAM;
+ addr->protocol = IPPROTO_IP;
+ break;
+ default: /* UDP and QUIC */
+ addr->socktype = SOCK_DGRAM;
+ addr->protocol = IPPROTO_UDP;
+ break;
+ }
addr->addrlen = ai->ai_addrlen;
if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
@@ -1636,6 +1655,24 @@ CURLcode Curl_socket(struct Curl_easy *data,
if(conn->transport == TRNSPRT_QUIC) {
/* QUIC sockets need to be nonblocking */
(void)curlx_nonblock(*sockfd, TRUE);
+ switch(addr->family) {
+#if defined(__linux__) && defined(IP_MTU_DISCOVER)
+ case AF_INET: {
+ int val = IP_PMTUDISC_DO;
+ (void)setsockopt(*sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &val,
+ sizeof(val));
+ break;
+ }
+#endif
+#if defined(__linux__) && defined(IPV6_MTU_DISCOVER)
+ case AF_INET6: {
+ int val = IPV6_PMTUDISC_DO;
+ (void)setsockopt(*sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val,
+ sizeof(val));
+ break;
+ }
+#endif
+ }
}
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
@@ -1645,20 +1682,6 @@ CURLcode Curl_socket(struct Curl_easy *data,
}
#endif
-#if defined(__linux__) && defined(IP_RECVERR)
- if(addr->socktype == SOCK_DGRAM) {
- int one = 1;
- switch(addr->family) {
- case AF_INET:
- (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one));
- break;
- case AF_INET6:
- (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
- break;
- }
- }
-#endif
-
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 1a055f58d..582ff0813 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index c03637a39..9e345b197 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -26,8 +28,8 @@
#include <curl/curl.h>
#include <stddef.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
+#ifdef HAVE_LIBZ
+#include <cm3p/zlib.h>
#endif
#ifdef HAVE_BROTLI
@@ -80,8 +82,9 @@ typedef enum {
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
-/* Writer parameters. */
-struct zlib_params {
+/* Deflate and gzip writer. */
+struct zlib_writer {
+ struct contenc_writer super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -133,7 +136,7 @@ exit_zlib(struct Curl_easy *data,
}
static CURLcode process_trailer(struct Curl_easy *data,
- struct zlib_params *zp)
+ struct zlib_writer *zp)
{
z_stream *z = &zp->z;
CURLcode result = CURLE_OK;
@@ -160,7 +163,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
struct contenc_writer *writer,
zlibInitState started)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
@@ -263,7 +266,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -283,7 +286,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
/* Set the compressed input when this function is called */
@@ -300,7 +303,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
@@ -312,7 +315,7 @@ static const struct content_encoding deflate_encoding = {
deflate_init_writer,
deflate_unencode_write,
deflate_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
@@ -320,7 +323,7 @@ static const struct content_encoding deflate_encoding = {
static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -437,7 +440,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(zp->zlib_init == ZLIB_INIT_GZIP) {
@@ -564,7 +567,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
@@ -576,15 +579,16 @@ static const struct content_encoding gzip_encoding = {
gzip_init_writer,
gzip_unencode_write,
gzip_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
#endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI
-/* Writer parameters. */
-struct brotli_params {
+/* Brotli writer. */
+struct brotli_writer {
+ struct contenc_writer super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -629,7 +633,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
if(!writer->downstream)
@@ -643,7 +647,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf;
char *decomp;
uint8_t *dst;
@@ -690,7 +694,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
+
(void) data;
if(bp->br) {
@@ -705,14 +710,15 @@ static const struct content_encoding brotli_encoding = {
brotli_init_writer,
brotli_unencode_write,
brotli_close_writer,
- sizeof(struct brotli_params)
+ sizeof(struct brotli_writer)
};
#endif
#ifdef HAVE_ZSTD
-/* Writer parameters. */
-struct zstd_params {
+/* Zstd writer. */
+struct zstd_writer {
+ struct contenc_writer super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
@@ -720,7 +726,8 @@ struct zstd_params {
static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(!writer->downstream)
@@ -736,7 +743,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
ZSTD_inBuffer in;
ZSTD_outBuffer out;
size_t errorCode;
@@ -775,7 +782,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
static void zstd_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(zp->decomp) {
@@ -794,7 +802,7 @@ static const struct content_encoding zstd_encoding = {
zstd_init_writer,
zstd_unencode_write,
zstd_close_writer,
- sizeof(struct zstd_params)
+ sizeof(struct zstd_writer)
};
#endif
@@ -827,7 +835,7 @@ static const struct content_encoding identity_encoding = {
identity_init_writer,
identity_unencode_write,
identity_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -919,7 +927,7 @@ static const struct content_encoding client_encoding = {
client_init_writer,
client_unencode_write,
client_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -962,7 +970,7 @@ static const struct content_encoding error_encoding = {
error_init_writer,
error_unencode_write,
error_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
/* Create an unencoding writer stage using the given handler. */
@@ -971,8 +979,10 @@ new_unencoding_writer(struct Curl_easy *data,
const struct content_encoding *handler,
struct contenc_writer *downstream)
{
- size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
- struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
+ struct contenc_writer *writer;
+
+ DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
+ writer = (struct contenc_writer *) calloc(1, handler->writersize);
if(writer) {
writer->handler = handler;
@@ -1026,19 +1036,23 @@ static const struct content_encoding *find_encoding(const char *name,
return NULL;
}
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
struct SingleRequest *k = &data->req;
+ int counter = 0;
do {
const char *name;
size_t namelen;
/* Parse a single encoding name. */
- while(ISSPACE(*enclist) || *enclist == ',')
+ while(ISBLANK(*enclist) || *enclist == ',')
enclist++;
name = enclist;
@@ -1066,6 +1080,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
+ if(++counter >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to %u content encodings",
+ counter);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
/* Stack the unencoding stage. */
writer = new_unencoding_writer(data, encoding, k->writer_stack);
if(!writer)
diff --git a/Utilities/cmcurl/lib/content_encoding.h b/Utilities/cmcurl/lib/content_encoding.h
index acfd0c27b..3c278cf72 100644
--- a/Utilities/cmcurl/lib/content_encoding.h
+++ b/Utilities/cmcurl/lib/content_encoding.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,13 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
struct contenc_writer {
const struct content_encoding *handler; /* Encoding handler. */
struct contenc_writer *downstream; /* Downstream writer. */
- void *params; /* Encoding-specific storage (variable length). */
};
/* Content encoding writer. */
@@ -40,7 +41,7 @@ struct content_encoding {
const char *buf, size_t nbytes);
void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
- size_t paramsize;
+ size_t writersize;
};
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 0c2d49b47..8eaedeeb7 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/***
@@ -33,8 +35,9 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
called before any cookies are set.
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *c, bool httpheader, char *lineptr,
- const char *domain, const char *path);
+ struct CookieInfo *c, bool httpheader, bool noexpire,
+ char *lineptr, const char *domain, const char *path,
+ bool secure);
The 'lineptr' parameter is a full "Set-cookie:" line as
received from a server.
@@ -96,8 +99,8 @@ Example set of cookies:
#include "curl_get_line.h"
#include "curl_memrchr.h"
#include "parsedate.h"
-#include "rand.h"
#include "rename.h"
+#include "fopen.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -439,6 +442,29 @@ static bool bad_domain(const char *domain)
}
/*
+ RFC 6265 section 4.1.1 says a server should accept this range:
+
+ cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+
+ But Firefox and Chrome as of June 2022 accept space, comma and double-quotes
+ fine. The prime reason for filtering out control bytes is that some HTTP
+ servers return 400 for requests that contain such.
+*/
+static int invalid_octets(const char *p)
+{
+ /* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */
+ static const char badoctets[] = {
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x0a"
+ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+ "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f"
+ };
+ size_t len;
+ /* scan for all the octets that are *not* in cookie-octet */
+ len = strcspn(p, badoctets);
+ return (p[len] != '\0');
+}
+
+/*
* Curl_cookie_add
*
* Add a single cookie line to the cookie keeping object. Be aware that
@@ -468,6 +494,8 @@ Curl_cookie_add(struct Curl_easy *data,
struct Cookie *clist;
struct Cookie *co;
struct Cookie *lastc = NULL;
+ struct Cookie *replace_co = NULL;
+ struct Cookie *replace_clist = NULL;
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
@@ -477,6 +505,10 @@ Curl_cookie_add(struct Curl_easy *data,
(void)data;
#endif
+ DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */
+ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT)
+ return NULL;
+
/* First, alloc and init a new struct for it */
co = calloc(1, sizeof(struct Cookie));
if(!co)
@@ -505,7 +537,7 @@ Curl_cookie_add(struct Curl_easy *data,
do {
/* we have a <what>=<this> pair or a stand-alone word here */
name[0] = what[0] = 0; /* init the buffers */
- if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
+ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\t\r\n=] =%"
MAX_NAME_TXT "[^;\r\n]",
name, what)) {
/*
@@ -559,6 +591,13 @@ Curl_cookie_add(struct Curl_easy *data,
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
+ /* Reject cookies with a TAB inside the content */
+ if(strchr(whatptr, '\t')) {
+ freecookie(co);
+ infof(data, "cookie contains TAB, dropping");
+ return NULL;
+ }
+
/*
* Check if we have a reserved prefix set before anything else, as we
* otherwise have to test for the prefix in both the cookie name and
@@ -586,6 +625,11 @@ Curl_cookie_add(struct Curl_easy *data,
badcookie = TRUE;
break;
}
+ if(invalid_octets(whatptr) || invalid_octets(name)) {
+ infof(data, "invalid octets in name/value, cookie dropped");
+ badcookie = TRUE;
+ break;
+ }
}
else if(!len) {
/*
@@ -628,7 +672,7 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
}
- else if(strcasecompare("domain", name)) {
+ else if(strcasecompare("domain", name) && whatptr[0]) {
bool is_ip;
/*
@@ -816,7 +860,7 @@ Curl_cookie_add(struct Curl_easy *data,
freecookie(co);
return NULL;
}
-
+ data->req.setcookies++;
}
else {
/*
@@ -1020,12 +1064,53 @@ Curl_cookie_add(struct Curl_easy *data,
}
#endif
+ /* A non-secure cookie may not overlay an existing secure cookie. */
myhash = cookiehash(co->domain);
clist = c->cookies[myhash];
- replace_old = FALSE;
while(clist) {
if(strcasecompare(clist->name, co->name)) {
/* the names are identical */
+ bool matching_domains = FALSE;
+
+ if(clist->domain && co->domain) {
+ if(strcasecompare(clist->domain, co->domain))
+ /* The domains are identical */
+ matching_domains = TRUE;
+ }
+ else if(!clist->domain && !co->domain)
+ matching_domains = TRUE;
+
+ if(matching_domains && /* the domains were identical */
+ clist->spath && co->spath && /* both have paths */
+ clist->secure && !co->secure && !secure) {
+ size_t cllen;
+ const char *sep;
+
+ /*
+ * A non-secure cookie may not overlay an existing secure cookie.
+ * For an existing cookie "a" with path "/login", refuse a new
+ * cookie "a" with for example path "/login/en", while the path
+ * "/loginhelper" is ok.
+ */
+
+ sep = strchr(clist->spath + 1, '/');
+
+ if(sep)
+ cllen = sep - clist->spath;
+ else
+ cllen = strlen(clist->spath);
+
+ if(strncasecompare(clist->spath, co->spath, cllen)) {
+ infof(data, "cookie '%s' for domain '%s' dropped, would "
+ "overlay an existing cookie", co->name, co->domain);
+ freecookie(co);
+ return NULL;
+ }
+ }
+ }
+
+ if(!replace_co && strcasecompare(clist->name, co->name)) {
+ /* the names are identical */
if(clist->domain && co->domain) {
if(strcasecompare(clist->domain, co->domain) &&
@@ -1040,30 +1125,7 @@ Curl_cookie_add(struct Curl_easy *data,
/* the domains were identical */
if(clist->spath && co->spath) {
- if(clist->secure && !co->secure && !secure) {
- size_t cllen;
- const char *sep;
-
- /*
- * A non-secure cookie may not overlay an existing secure cookie.
- * For an existing cookie "a" with path "/login", refuse a new
- * cookie "a" with for example path "/login/en", while the path
- * "/loginhelper" is ok.
- */
-
- sep = strchr(clist->spath + 1, '/');
-
- if(sep)
- cllen = sep - clist->spath;
- else
- cllen = strlen(clist->spath);
-
- if(strncasecompare(clist->spath, co->spath, cllen)) {
- freecookie(co);
- return NULL;
- }
- }
- else if(strcasecompare(clist->spath, co->spath))
+ if(strcasecompare(clist->spath, co->spath))
replace_old = TRUE;
else
replace_old = FALSE;
@@ -1085,42 +1147,37 @@ Curl_cookie_add(struct Curl_easy *data,
freecookie(co);
return NULL;
}
-
if(replace_old) {
- co->next = clist->next; /* get the next-pointer first */
-
- /* when replacing, creationtime is kept from old */
- co->creationtime = clist->creationtime;
-
- /* then free all the old pointers */
- free(clist->name);
- free(clist->value);
- free(clist->domain);
- free(clist->path);
- free(clist->spath);
- free(clist->expirestr);
- free(clist->version);
- free(clist->maxage);
-
- *clist = *co; /* then store all the new data */
-
- free(co); /* free the newly allocated memory */
- co = clist; /* point to the previous struct instead */
-
- /*
- * We have replaced a cookie, now skip the rest of the list but make
- * sure the 'lastc' pointer is properly set
- */
- do {
- lastc = clist;
- clist = clist->next;
- } while(clist);
- break;
+ replace_co = co;
+ replace_clist = clist;
}
}
lastc = clist;
clist = clist->next;
}
+ if(replace_co) {
+ co = replace_co;
+ clist = replace_clist;
+ co->next = clist->next; /* get the next-pointer first */
+
+ /* when replacing, creationtime is kept from old */
+ co->creationtime = clist->creationtime;
+
+ /* then free all the old pointers */
+ free(clist->name);
+ free(clist->value);
+ free(clist->domain);
+ free(clist->path);
+ free(clist->spath);
+ free(clist->expirestr);
+ free(clist->version);
+ free(clist->maxage);
+
+ *clist = *co; /* then store all the new data */
+
+ free(co); /* free the newly allocated memory */
+ co = clist;
+ }
if(c->running)
/* Only show this when NOT reading the cookies from a file */
@@ -1357,7 +1414,8 @@ static struct Cookie *dup_cookie(struct Cookie *src)
*
* It shall only return cookies that haven't expired.
*/
-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
+ struct CookieInfo *c,
const char *host, const char *path,
bool secure)
{
@@ -1412,6 +1470,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
mainco = newco;
matches++;
+ if(matches >= MAX_COOKIE_SEND_AMOUNT) {
+ infof(data, "Included max number of cookies (%zu) in request!",
+ matches);
+ break;
+ }
}
else
goto fail;
@@ -1613,20 +1676,9 @@ static CURLcode cookie_output(struct Curl_easy *data,
use_stdout = TRUE;
}
else {
- unsigned char randsuffix[9];
-
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return 2;
-
- tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
- if(!tempstore)
- return CURLE_OUT_OF_MEMORY;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out) {
- error = CURLE_WRITE_ERROR;
+ error = Curl_fopen(data, filename, &out, &tempstore);
+ if(error)
goto error;
- }
}
fputs("# Netscape HTTP Cookie File\n"
@@ -1673,7 +1725,7 @@ static CURLcode cookie_output(struct Curl_easy *data,
if(!use_stdout) {
fclose(out);
out = NULL;
- if(Curl_rename(tempstore, filename)) {
+ if(tempstore && Curl_rename(tempstore, filename)) {
unlink(tempstore);
error = CURLE_WRITE_ERROR;
goto error;
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index 0ffe08e63..abc0a2e8a 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -81,10 +83,26 @@ struct CookieInfo {
*/
#define MAX_COOKIE_LINE 5000
-/* This is the maximum length of a cookie name or content we deal with: */
+/* Maximum length of an incoming cookie name or content we deal with. Longer
+ cookies are ignored. */
#define MAX_NAME 4096
#define MAX_NAME_TXT "4095"
+/* Maximum size for an outgoing cookie line libcurl will use in an http
+ request. This is the default maximum length used in some versions of Apache
+ httpd. */
+#define MAX_COOKIE_HEADER_LEN 8190
+
+/* Maximum number of cookies libcurl will send in a single request, even if
+ there might be more cookies that match. One reason to cap the number is to
+ keep the maximum HTTP request within the maximum allowed size. */
+#define MAX_COOKIE_SEND_AMOUNT 150
+
+/* Maximum number of Set-Cookie: lines accepted in a single response. If more
+ such header lines are received, they are ignored. This value must be less
+ than 256 since an unsigned char is used to count. */
+#define MAX_SET_COOKIE_AMOUNT 50
+
struct Curl_easy;
/*
* Add a cookie to the internal list of cookies. The domain and path arguments
@@ -97,7 +115,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
const char *domain, const char *path,
bool secure);
-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host,
+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
+ struct CookieInfo *c, const char *host,
const char *path, bool secure);
void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 842fd7fe2..72e778b34 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -277,7 +279,7 @@ Curl_he2ai(const struct hostent *he, int port)
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size;
- size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
+ size_t namelen = strlen(he->h_name) + 1; /* include null-terminatior */
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index 73a8c1b33..b778121a7 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_base64.h b/Utilities/cmcurl/lib/curl_base64.h
index 4cb9d7353..85368a163 100644
--- a/Utilities/cmcurl/lib/curl_base64.h
+++ b/Utilities/cmcurl/lib/curl_base64.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 4a6f90e3a..b8a58c831 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -18,15 +18,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* lib/curl_config.h.in. Generated somehow by cmake. */
#include <cm3p/kwiml/abi.h>
-/* when building libcurl itself */
-#cmakedefine BUILDING_LIBCURL 1
-
-/* to disable alt-svc */
+/* disables alt-svc */
#cmakedefine CURL_DISABLE_ALTSVC 1
/* disables cookies support */
@@ -138,9 +137,6 @@
/* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1
-/* Define to 1 if you have the <alloca.h> header file. */
-#cmakedefine HAVE_ALLOCA_H 1
-
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1
@@ -150,6 +146,12 @@
/* Define to 1 if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H 1
+/* Define to 1 if you have _Atomic support. */
+#cmakedefine HAVE_ATOMIC 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#cmakedefine HAVE_FCHMOD 1
+
/* Define to 1 if you have the `basename' function. */
#cmakedefine HAVE_BASENAME 1
@@ -165,12 +167,6 @@
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1
-/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
-#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#cmakedefine HAVE_DLFCN_H 1
-
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H 1
@@ -192,15 +188,15 @@
/* Define to 1 if you have a working getaddrinfo function. */
#cmakedefine HAVE_GETADDRINFO 1
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#cmakedefine HAVE_GETADDRINFO_THREADSAFE 1
+
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID 1
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
-/* Define to 1 if you have the gethostbyname function. */
-#cmakedefine HAVE_GETHOSTBYNAME 1
-
/* Define to 1 if you have the gethostbyname_r function. */
#cmakedefine HAVE_GETHOSTBYNAME_R 1
@@ -225,9 +221,6 @@
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
-/* Define to 1 if you have the `getprotobyname' function. */
-#cmakedefine HAVE_GETPROTOBYNAME 1
-
/* Define to 1 if you have the `getpeername' function. */
#cmakedefine HAVE_GETPEERNAME 1
@@ -279,18 +272,9 @@
/* Define to 1 if you have the `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR 1
-/* Define to 1 if you have the `idn_free' function. */
-#cmakedefine HAVE_IDN_FREE 1
-
-/* Define to 1 if you have the <idn-free.h> header file. */
-#cmakedefine HAVE_IDN_FREE_H 1
-
/* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1
-/* Define to 1 if you have the `inet_addr' function. */
-#cmakedefine HAVE_INET_ADDR 1
-
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#cmakedefine HAVE_INET_NTOP 1
@@ -306,9 +290,6 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
-/* Define to 1 if you have the ioctl function. */
-#cmakedefine HAVE_IOCTL 1
-
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
@@ -331,21 +312,9 @@
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
-/* if you have the Kerberos4 libraries (including -ldes) */
-#cmakedefine HAVE_KRB4 1
-
-/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
-#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1
-
-/* Define to 1 if you have the <krb.h> header file. */
-#cmakedefine HAVE_KRB_H 1
-
/* Define to 1 if you have the lber.h header file. */
#cmakedefine HAVE_LBER_H 1
-/* Define to 1 if you have the ldapssl.h header file. */
-#cmakedefine HAVE_LDAPSSL_H 1
-
/* Define to 1 if you have the ldap.h header file. */
#cmakedefine HAVE_LDAP_H 1
@@ -367,24 +336,12 @@
/* Define to 1 if you have the idn2.h header file. */
#cmakedefine HAVE_IDN2_H 1
-/* Define to 1 if you have the `resolv' library (-lresolv). */
-#cmakedefine HAVE_LIBRESOLV 1
-
-/* Define to 1 if you have the `resolve' library (-lresolve). */
-#cmakedefine HAVE_LIBRESOLVE 1
-
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET 1
/* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 1
-/* Define to 1 if you have the <libssh2.h> header file. */
-#cmakedefine HAVE_LIBSSH2_H 1
-
-/* Define to 1 if you have the <libssh/libssh.h> header file. */
-#cmakedefine HAVE_LIBSSH_LIBSSH_H 1
-
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
@@ -397,20 +354,11 @@
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1
-/* Define to 1 if you have a working localtime_r function. */
-#cmakedefine HAVE_LOCALTIME_R 1
-
/* Define to 1 if the compiler supports the 'long long' data type. */
#if KWIML_ABI_SIZEOF_LONG_LONG
# define HAVE_LONGLONG 1
#endif
-/* Define to 1 if you have the malloc.h header file. */
-#cmakedefine HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#cmakedefine HAVE_MEMORY_H 1
-
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL 1
@@ -429,42 +377,12 @@
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
-/* Define to 1 if NI_WITHSCOPEID exists and works. */
-#cmakedefine HAVE_NI_WITHSCOPEID 1
-
/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
#cmakedefine HAVE_OLD_GSSMIT 1
-/* Define to 1 if you have the <openssl/crypto.h> header file. */
-#cmakedefine HAVE_OPENSSL_CRYPTO_H 1
-
-/* Define to 1 if you have the <openssl/err.h> header file. */
-#cmakedefine HAVE_OPENSSL_ERR_H 1
-
-/* Define to 1 if you have the <openssl/pem.h> header file. */
-#cmakedefine HAVE_OPENSSL_PEM_H 1
-
-/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
-#cmakedefine HAVE_OPENSSL_PKCS12_H 1
-
-/* Define to 1 if you have the <openssl/rsa.h> header file. */
-#cmakedefine HAVE_OPENSSL_RSA_H 1
-
-/* Define to 1 if you have the <openssl/ssl.h> header file. */
-#cmakedefine HAVE_OPENSSL_SSL_H 1
-
-/* Define to 1 if you have the <openssl/x509.h> header file. */
-#cmakedefine HAVE_OPENSSL_X509_H 1
-
-/* Define to 1 if you have the <pem.h> header file. */
-#cmakedefine HAVE_PEM_H 1
-
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
-/* Define to 1 if you have a working poll function. */
-#cmakedefine HAVE_POLL 1
-
/* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE 1
@@ -483,18 +401,9 @@
/* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD 1
-/* Define to 1 if you have the `RAND_screen' function. */
-#cmakedefine HAVE_RAND_SCREEN 1
-
-/* Define to 1 if you have the `RAND_status' function. */
-#cmakedefine HAVE_RAND_STATUS 1
-
/* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV 1
-/* Define to 1 if you have the recvfrom function. */
-#cmakedefine HAVE_RECVFROM 1
-
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1
@@ -522,9 +431,6 @@
/* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT 1
-/* Define to 1 if you have the setsockopt function. */
-#cmakedefine HAVE_SETSOCKOPT 1
-
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
@@ -549,27 +455,27 @@
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET 1
+/* Define to 1 if you have the socketpair function. */
+#cmakedefine HAVE_SOCKETPAIR 1
+
/* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H 1
+/* Define to 1 if you have the <stdatomic.h> header file. */
+#cmakedefine HAVE_STDATOMIC_H 1
+
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
-/* Define to 1 if you have the <stdio.h> header file. */
-#cmakedefine HAVE_STDIO_H 1
-
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
-/* Define to 1 if you have the strcasestr function. */
-#cmakedefine HAVE_STRCASESTR 1
-
/* Define to 1 if you have the strcmpi function. */
#cmakedefine HAVE_STRCMPI 1
@@ -588,18 +494,9 @@
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
-/* Define to 1 if you have the strncmpi function. */
-#cmakedefine HAVE_STRNCMPI 1
-
-/* Define to 1 if you have the strnicmp function. */
-#cmakedefine HAVE_STRNICMP 1
-
/* Define to 1 if you have the <stropts.h> header file. */
#cmakedefine HAVE_STROPTS_H 1
-/* Define to 1 if you have the strstr function. */
-#cmakedefine HAVE_STRSTR 1
-
/* Define to 1 if you have the strtok_r function. */
#cmakedefine HAVE_STRTOK_R 1
@@ -645,9 +542,6 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#cmakedefine HAVE_SYS_UIO_H 1
-
/* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H 1
@@ -663,15 +557,6 @@
/* Define to 1 if you have the <time.h> header file. */
#cmakedefine HAVE_TIME_H 1
-/* Define to 1 if you have the <tld.h> header file. */
-#cmakedefine HAVE_TLD_H 1
-
-/* Define to 1 if you have the `tld_strerror' function. */
-#cmakedefine HAVE_TLD_STRERROR 1
-
-/* Define to 1 if you have the `uname' function. */
-#cmakedefine HAVE_UNAME 1
-
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
@@ -690,9 +575,6 @@
/* Define to 1 if compiler supports old gcc variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
-/* Define to 1 if you have the winber.h header file. */
-#cmakedefine HAVE_WINBER_H 1
-
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1
@@ -705,28 +587,12 @@
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
-/* Define to 1 if you have the writev function. */
-#cmakedefine HAVE_WRITEV 1
-
/* Define to 1 if you have the ws2tcpip.h header file. */
#cmakedefine HAVE_WS2TCPIP_H 1
-/* Define to 1 if you have the <x509.h> header file. */
-#cmakedefine HAVE_X509_H 1
-
/* Define if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
-/* if you have the zlib.h header file */
-#cmakedefine HAVE_ZLIB_H 1
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#cmakedefine LT_OBJDIR ${LT_OBJDIR}
-
-/* If you lack a fine basename() prototype */
-#cmakedefine NEED_BASENAME_PROTO 1
-
/* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1
@@ -760,84 +626,6 @@
/* a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
-/* Define to the type of arg 1 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1}
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2}
-
-/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1
-
-/* Define to the type of arg 3 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3}
-
-/* Define to the type of arg 4 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4}
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5}
-
-/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6}
-
-/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1
-
-/* Define to the function return type for recvfrom. */
-#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV}
-
-/* Define to the type of arg 1 for recv. */
-#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
-
-/* Define to the type of arg 2 for recv. */
-#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
-
-/* Define to the type of arg 3 for recv. */
-#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
-
-/* Define to the type of arg 4 for recv. */
-#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
-
-/* Define to the function return type for recv. */
-#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
-
-/* Define to the type qualifier of arg 5 for select. */
-#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
-
-/* Define to the type of arg 1 for select. */
-#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
-
-/* Define to the type of args 2, 3 and 4 for select. */
-#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
-
-/* Define to the type of arg 5 for select. */
-#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
-
-/* Define to the function return type for select. */
-#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV}
-
-/* Define to the type qualifier of arg 2 for send. */
-#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
-
-/* Define to the type of arg 1 for send. */
-#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
-
-/* Define to the type of arg 2 for send. */
-#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
-
-/* Define to the type of arg 3 for send. */
-#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
-
-/* Define to the type of arg 4 for send. */
-#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
-
-/* Define to the function return type for send. */
-#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
-
/*
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
As per CMake documentation on CheckTypeSize, C preprocessor code is
@@ -882,9 +670,6 @@ ${SIZEOF_TIME_T_CODE}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
-/* Define to the type of arg 3 for strerror_r. */
-#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3}
-
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME 1
@@ -918,6 +703,9 @@ ${SIZEOF_TIME_T_CODE}
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 1
+/* if libPSL is in use */
+#cmakedefine USE_LIBPSL 1
+
/* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL 1
@@ -967,9 +755,6 @@ ${SIZEOF_TIME_T_CODE}
/* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1
-/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
-#cmakedefine USE_YASSLEMUL 1
-
/* Version number of package */
#cmakedefine VERSION ${VERSION}
@@ -1023,3 +808,6 @@ ${SIZEOF_TIME_T_CODE}
/* to make the compiler know the prototypes of Windows IDN APIs */
#cmakedefine WANT_IDN_PROTOTYPES 1
+
+/* Define to 1 to enable websocket support. */
+#cmakedefine USE_WEBSOCKETS 1
diff --git a/Utilities/cmcurl/lib/curl_ctype.c b/Utilities/cmcurl/lib/curl_ctype.c
deleted file mode 100644
index 233a69e76..000000000
--- a/Utilities/cmcurl/lib/curl_ctype.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#undef _U
-#define _U (1<<0) /* upper case */
-#undef _L
-#define _L (1<<1) /* lower case */
-#undef _N
-#define _N (1<<2) /* decimal numerical digit */
-#undef _S
-#define _S (1<<3) /* space */
-#undef _P
-#define _P (1<<4) /* punctuation */
-#undef _C
-#define _C (1<<5) /* control */
-#undef _X
-#define _X (1<<6) /* hexadecimal letter */
-#undef _B
-#define _B (1<<7) /* blank */
-
-static const unsigned char ascii[128] = {
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _S|_B, _P, _P, _P, _P, _P, _P, _P,
- _P, _P, _P, _P, _P, _P, _P, _P,
- _N, _N, _N, _N, _N, _N, _N, _N,
- _N, _N, _P, _P, _P, _P, _P, _P,
- _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _P, _P, _P, _P, _P,
- _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _P, _P, _P, _P, _C
-};
-
-int Curl_isspace(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _S);
-}
-
-int Curl_isdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _N);
-}
-
-int Curl_isalnum(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_U|_L));
-}
-
-int Curl_isxdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X));
-}
-
-int Curl_isgraph(int c)
-{
- if((c < 0) || (c >= 0x80) || (c == ' '))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isprint(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isalpha(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U|_L));
-}
-
-int Curl_isupper(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U));
-}
-
-int Curl_islower(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_L));
-}
-
-int Curl_iscntrl(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_C));
-}
-
diff --git a/Utilities/cmcurl/lib/curl_ctype.h b/Utilities/cmcurl/lib/curl_ctype.h
index 2fa749dca..dc6b8cab8 100644
--- a/Utilities/cmcurl/lib/curl_ctype.h
+++ b/Utilities/cmcurl/lib/curl_ctype.h
@@ -20,34 +20,28 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
-#include "curl_setup.h"
+#define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f'))
+#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F'))
-int Curl_isspace(int c);
-int Curl_isdigit(int c);
-int Curl_isalnum(int c);
-int Curl_isxdigit(int c);
-int Curl_isgraph(int c);
-int Curl_isprint(int c);
-int Curl_isalpha(int c);
-int Curl_isupper(int c);
-int Curl_islower(int c);
-int Curl_iscntrl(int c);
+#define ISLOWCNTRL(x) ((x) >= 0 && ((x) <= 0x1f))
+#define IS7F(x) ((x) == 0x7f)
-#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
-#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
-#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+#define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d))
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
+#define ISPRINT(x) (ISLOWPRINT(x) || (((x) >= ' ') && ((x) <= 0x7e)))
+#define ISGRAPH(x) (ISLOWPRINT(x) || (((x) > ' ') && ((x) <= 0x7e)))
+#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
+#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
+#define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
+#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
+#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
+#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
+#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
+#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
+#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
#endif /* HEADER_CURL_CTYPE_H */
diff --git a/Utilities/cmcurl/lib/curl_des.c b/Utilities/cmcurl/lib/curl_des.c
index 5f28ef4f3..a2bf648c2 100644
--- a/Utilities/cmcurl/lib/curl_des.c
+++ b/Utilities/cmcurl/lib/curl_des.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -39,7 +41,7 @@
*
* The function is a port of the Java based oddParity() function over at:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
*
* Parameters:
*
diff --git a/Utilities/cmcurl/lib/curl_des.h b/Utilities/cmcurl/lib/curl_des.h
index 3d0fd9260..c1c167471 100644
--- a/Utilities/cmcurl/lib/curl_des.h
+++ b/Utilities/cmcurl/lib/curl_des.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index ecde74bfb..3cc7734f3 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index 4e12d7da4..758d55f2c 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* Converts a 16-bit integer from little endian */
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index 4bfa58598..0dd1eb5ef 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.h b/Utilities/cmcurl/lib/curl_fnmatch.h
index 1c80ea779..8324be533 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.h
+++ b/Utilities/cmcurl/lib/curl_fnmatch.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#define CURL_FNMATCH_MATCH 0
diff --git a/Utilities/cmcurl/lib/curl_get_line.c b/Utilities/cmcurl/lib/curl_get_line.c
index 8f3b0bd8c..22e3705f4 100644
--- a/Utilities/cmcurl/lib/curl_get_line.c
+++ b/Utilities/cmcurl/lib/curl_get_line.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,12 +18,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
- !defined(CURL_DISABLE_HSTS)
+ !defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
#include "curl_memory.h"
@@ -31,8 +33,8 @@
#include "memdebug.h"
/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
+ * Curl_get_line() makes sure to only return complete whole lines that fit in
+ * 'len' bytes and end with a newline.
*/
char *Curl_get_line(char *buf, int len, FILE *input)
{
diff --git a/Utilities/cmcurl/lib/curl_get_line.h b/Utilities/cmcurl/lib/curl_get_line.h
index 597aa09a9..b2a534d00 100644
--- a/Utilities/cmcurl/lib/curl_get_line.h
+++ b/Utilities/cmcurl/lib/curl_get_line.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* get_line() makes sure to only return complete whole lines that fit in 'len'
diff --git a/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c
index 2d5ff61cf..4747e938d 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.c
+++ b/Utilities/cmcurl/lib/curl_gethostname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_gethostname.h b/Utilities/cmcurl/lib/curl_gethostname.h
index 2161c40ac..b7360969a 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.h
+++ b/Utilities/cmcurl/lib/curl_gethostname.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* Hostname buffer size */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index 1543a0ff4..01ab48ec3 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -89,7 +91,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
OM_uint32 maj_stat;
OM_uint32 min_stat;
OM_uint32 msg_ctx = 0;
- gss_buffer_desc status_string;
+ gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
do {
maj_stat = gss_display_status(&min_stat,
@@ -98,10 +100,12 @@ static size_t display_gss_error(OM_uint32 status, int type,
GSS_C_NO_OID,
&msg_ctx,
&status_string);
- if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
- len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
- "%.*s. ", (int)status_string.length,
- (char *)status_string.value);
+ if(maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
+ if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
+ len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
+ "%.*s. ", (int)status_string.length,
+ (char *)status_string.value);
+ }
}
gss_release_buffer(&min_stat, &status_string);
} while(!GSS_ERROR(maj_stat) && msg_ctx);
diff --git a/Utilities/cmcurl/lib/curl_gssapi.h b/Utilities/cmcurl/lib/curl_gssapi.h
index 466d09ed0..b4ed482aa 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.h
+++ b/Utilities/cmcurl/lib/curl_gssapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 5755655d0..36c0bd62e 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/lib/curl_hmac.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,10 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
+
#define HMAC_MD5_LENGTH 16
typedef CURLcode (* HMAC_hinit_func)(void *context);
diff --git a/Utilities/cmcurl/lib/curl_krb5.h b/Utilities/cmcurl/lib/curl_krb5.h
index ca0684074..ccd6f10e3 100644
--- a/Utilities/cmcurl/lib/curl_krb5.h
+++ b/Utilities/cmcurl/lib/curl_krb5.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
struct Curl_sec_client_mech {
diff --git a/Utilities/cmcurl/lib/curl_ldap.h b/Utilities/cmcurl/lib/curl_ldap.h
index 124e18b13..ba3ede426 100644
--- a/Utilities/cmcurl/lib/curl_ldap.h
+++ b/Utilities/cmcurl/lib/curl_ldap.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_LDAP
extern const struct Curl_handler Curl_handler_ldap;
diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h
index f9dafcb53..8049355cf 100644
--- a/Utilities/cmcurl/lib/curl_md4.h
+++ b/Utilities/cmcurl/lib/curl_md4.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_md5.h b/Utilities/cmcurl/lib/curl_md5.h
index b7d7c1f5d..789329654 100644
--- a/Utilities/cmcurl/lib/curl_md5.h
+++ b/Utilities/cmcurl/lib/curl_md5.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h
index 580629063..092fc9f75 100644
--- a/Utilities/cmcurl/lib/curl_memory.h
+++ b/Utilities/cmcurl/lib/curl_memory.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/curl_memrchr.c b/Utilities/cmcurl/lib/curl_memrchr.c
index 0bd845f69..c329a6176 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.c
+++ b/Utilities/cmcurl/lib/curl_memrchr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_memrchr.h b/Utilities/cmcurl/lib/curl_memrchr.h
index c8394bb43..e7654e1d9 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.h
+++ b/Utilities/cmcurl/lib/curl_memrchr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_multibyte.c b/Utilities/cmcurl/lib/curl_multibyte.c
index 32c03a5b7..309dccbfe 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.c
+++ b/Utilities/cmcurl/lib/curl_multibyte.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/curl_multibyte.h b/Utilities/cmcurl/lib/curl_multibyte.h
index 491155e6a..929714873 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.h
+++ b/Utilities/cmcurl/lib/curl_multibyte.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index f3b8b130f..38e193c18 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -27,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -58,14 +60,19 @@
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
-#ifdef USE_WOLFSSL
-#include <wolfssl/options.h>
-#endif
-
+#if defined(USE_OPENSSL)
# include <openssl/des.h>
# include <openssl/md5.h>
# include <openssl/ssl.h>
# include <openssl/rand.h>
+#else
+# include <wolfssl/options.h>
+# include <wolfssl/openssl/des.h>
+# include <wolfssl/openssl/md5.h>
+# include <wolfssl/openssl/ssl.h>
+# include <wolfssl/openssl/rand.h>
+#endif
+
# if (defined(OPENSSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER < 0x00907001L)) && !defined(USE_WOLFSSL)
# define DES_key_schedule des_key_schedule
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index 5e52bb26d..60444c9dc 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -35,10 +37,10 @@
#define NTLM_NEEDS_NSS_INIT
#endif
-#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
#ifdef USE_WOLFSSL
# include <wolfssl/options.h>
-#endif
+# include <wolfssl/openssl/ssl.h>
+#elif defined(USE_OPENSSL)
# include <openssl/ssl.h>
#endif
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 5a3bc3c89..33dcf0ce2 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -28,7 +30,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.h b/Utilities/cmcurl/lib/curl_ntlm_wb.h
index 961b56873..1f04db8c3 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_path.c b/Utilities/cmcurl/lib/curl_path.c
index a1669d12f..b55e83047 100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl AND ISC
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -120,7 +122,8 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
bool relativePath = false;
static const char WHITESPACE[] = " \t\r\n";
- if(!*cp) {
+ DEBUGASSERT(homedir);
+ if(!*cp || !homedir) {
*cpp = NULL;
*path = NULL;
return CURLE_QUOTE_ERROR;
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index a376bd1d2..98e56eaad 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_printf.h b/Utilities/cmcurl/lib/curl_printf.h
index 9fa625f10..3823828cd 100644
--- a/Utilities/cmcurl/lib/curl_printf.h
+++ b/Utilities/cmcurl/lib/curl_printf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
index 24bdb3052..dd92d05b3 100644
--- a/Utilities/cmcurl/lib/curl_range.c
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -45,7 +47,7 @@ CURLcode Curl_range(struct Curl_easy *data)
from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW)
diff --git a/Utilities/cmcurl/lib/curl_range.h b/Utilities/cmcurl/lib/curl_range.h
index 0a07baf14..33570abc2 100644
--- a/Utilities/cmcurl/lib/curl_range.h
+++ b/Utilities/cmcurl/lib/curl_range.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index 2fa026796..b0c371041 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_rtmp.h b/Utilities/cmcurl/lib/curl_rtmp.h
index f45fa71d1..f856085dc 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.h
+++ b/Utilities/cmcurl/lib/curl_rtmp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2020, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) 2010 - 2022, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef USE_LIBRTMP
extern const struct Curl_handler Curl_handler_rtmp;
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 48d6625ba..9684ee476 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2195 CRAM-MD5 authentication
* RFC2617 Basic and Digest Access Authentication
* RFC2831 DIGEST-MD5 authentication
diff --git a/Utilities/cmcurl/lib/curl_sasl.h b/Utilities/cmcurl/lib/curl_sasl.h
index d377ae7bc..c709d56a6 100644
--- a/Utilities/cmcurl/lib/curl_sasl.h
+++ b/Utilities/cmcurl/lib/curl_sasl.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 3dd595018..c3ad25f99 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -20,12 +20,19 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES)
#define CURL_NO_OLDIES
#endif
+/* define mingw version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */
+#ifdef __MINGW32__
+#include <_mingw.h>
+#endif
+
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
@@ -155,8 +162,6 @@
/* please, do it beyond the point further indicated in this file. */
/* ================================================================ */
-#include <curl/curl.h>
-
/*
* Disable other protocols when http is the only one desired.
*/
@@ -216,7 +221,7 @@
/* ================================================================ */
/* No system header file shall be included in this file before this */
-/* point. The only allowed ones are those included from curl/system.h */
+/* point. */
/* ================================================================ */
/*
@@ -243,6 +248,8 @@
# include "setup-win32.h"
#endif
+#include <curl/system.h>
+
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
@@ -271,14 +278,41 @@
#endif
#ifdef __AMIGA__
+# ifdef __amigaos4__
+# define __USE_INLINE__
+ /* use our own resolver which uses runtime feature detection */
+# define CURLRES_AMIGA
+ /* getaddrinfo() currently crashes bsdsocket.library, so disable */
+# undef HAVE_GETADDRINFO
+# if !(defined(__NEWLIB__) || \
+ (defined(__CLIB2__) && defined(__THREAD_SAFE)))
+ /* disable threaded resolver with clib2 - requires newlib or clib-ts */
+# undef USE_THREADS_POSIX
+# endif
+# endif
# include <exec/types.h>
# include <exec/execbase.h>
# include <proto/exec.h>
# include <proto/dos.h>
# include <unistd.h>
-# ifdef HAVE_PROTO_BSDSOCKET_H
-# include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
-# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
+# if defined(HAVE_PROTO_BSDSOCKET_H) && \
+ (!defined(__amigaos4__) || defined(USE_AMISSL))
+ /* use bsdsocket.library directly, instead of libc networking functions */
+# include <proto/bsdsocket.h>
+# ifdef __amigaos4__
+ int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *errorfds, struct timeval *timeout);
+# define select(a,b,c,d,e) Curl_amiga_select(a,b,c,d,e)
+# else
+# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
+# endif
+ /* must not use libc's fcntl() on bsdsocket.library sockfds! */
+# undef HAVE_FCNTL
+# undef HAVE_FCNTL_O_NONBLOCK
+# else
+ /* use libc networking and hence close() and fnctl() */
+# undef HAVE_CLOSESOCKET_CAMEL
+# undef HAVE_IOCTLSOCKET_CAMEL
# endif
/*
* In clib2 arpa/inet.h warns that some prototypes may clash
@@ -292,8 +326,10 @@
#include <assert.h>
#endif
-#ifdef __TANDEM /* for nsr-tandem-nsk systems */
-#include <floss.h>
+#ifdef __TANDEM /* for ns*-tandem-nsk systems */
+# if ! defined __LP64
+# include <floss.h> /* FLOSS is only used for 32-bit builds. */
+# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
@@ -571,7 +607,6 @@
/* now undef the stock libc functions just to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
-# undef HAVE_GETHOSTBYNAME
#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
@@ -722,12 +757,12 @@
#define SHUT_RDWR 0x02
#endif
-/* Define S_ISREG if not defined by system headers, f.e. MSVC */
+/* Define S_ISREG if not defined by system headers, e.g. MSVC */
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
-/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
+/* Define S_ISDIR if not defined by system headers, e.g. MSVC */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
@@ -811,6 +846,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#if defined(USE_NGTCP2) || defined(USE_QUICHE) || defined(USE_MSH3)
#define ENABLE_QUIC
+#define USE_HTTP3
#endif
#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index 38018d23c..f09b00f9f 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
@@ -31,7 +33,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#include <ctype.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
@@ -86,6 +87,8 @@
#include <sys/socket.h>
#endif
+#include "functypes.h"
+
#ifdef __hpux
# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
# ifdef OLD_APP32_64BIT_OFF_T
@@ -148,20 +151,10 @@ struct timeval {
* SEND_TYPE_RETV must also be defined.
*/
-#if !defined(RECV_TYPE_ARG1) || \
- !defined(RECV_TYPE_ARG2) || \
- !defined(RECV_TYPE_ARG3) || \
- !defined(RECV_TYPE_ARG4) || \
- !defined(RECV_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recv
- /* */
-#else
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
(RECV_TYPE_ARG2)(y), \
(RECV_TYPE_ARG3)(z), \
(RECV_TYPE_ARG4)(0))
-#endif
#else /* HAVE_RECV */
#ifndef sread
/* */
@@ -178,21 +171,10 @@ struct timeval {
(SEND_TYPE_ARG3)(z))
#elif defined(HAVE_SEND)
-#if !defined(SEND_TYPE_ARG1) || \
- !defined(SEND_QUAL_ARG2) || \
- !defined(SEND_TYPE_ARG2) || \
- !defined(SEND_TYPE_ARG3) || \
- !defined(SEND_TYPE_ARG4) || \
- !defined(SEND_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_send
- /* */
-#else
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
(SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), \
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
-#endif
#else /* HAVE_SEND */
#ifndef swrite
/* */
@@ -202,46 +184,6 @@ struct timeval {
#endif /* HAVE_SEND */
-#if 0
-#if defined(HAVE_RECVFROM)
-/*
- * Currently recvfrom is only used on udp sockets.
- */
-#if !defined(RECVFROM_TYPE_ARG1) || \
- !defined(RECVFROM_TYPE_ARG2) || \
- !defined(RECVFROM_TYPE_ARG3) || \
- !defined(RECVFROM_TYPE_ARG4) || \
- !defined(RECVFROM_TYPE_ARG5) || \
- !defined(RECVFROM_TYPE_ARG6) || \
- !defined(RECVFROM_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recvfrom
- /* */
-#else
-#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \
- (RECVFROM_TYPE_ARG2 *)(b), \
- (RECVFROM_TYPE_ARG3) (bl), \
- (RECVFROM_TYPE_ARG4) (0), \
- (RECVFROM_TYPE_ARG5 *)(f), \
- (RECVFROM_TYPE_ARG6 *)(fl))
-#endif
-#else /* HAVE_RECVFROM */
-#ifndef sreadfrom
- /* */
- Error Missing_definition_of_macro_sreadfrom
- /* */
-#endif
-#endif /* HAVE_RECVFROM */
-
-
-#ifdef RECVFROM_TYPE_ARG6_IS_VOID
-# define RECVFROM_ARG6_T int
-#else
-# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6
-#endif
-#endif /* if 0 */
-
-
/*
* Function-like macro definition used to close a socket.
*/
@@ -267,9 +209,6 @@ struct timeval {
# define sfcntl fcntl
#endif
-#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
-
-
/*
* 'bool' stuff compatible with HP-UX headers.
*/
@@ -306,6 +245,14 @@ struct timeval {
# define HAVE_BOOL_T
#endif
+/* the type we use for storing a single boolean bit */
+#ifdef _MSC_VER
+typedef bool bit;
+#define BIT(x) bool x
+#else
+typedef unsigned int bit;
+#define BIT(x) bit x:1
+#endif
/*
* Redefine TRUE and FALSE too, to catch current use. With this
diff --git a/Utilities/cmcurl/lib/curl_sha256.h b/Utilities/cmcurl/lib/curl_sha256.h
index 2b7890a03..754c761fb 100644
--- a/Utilities/cmcurl/lib/curl_sha256.h
+++ b/Utilities/cmcurl/lib/curl_sha256.h
@@ -21,9 +21,12 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
#include "curl_hmac.h"
extern const struct HMAC_params Curl_HMAC_SHA256[1];
diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c
index 339bf549f..33108c48e 100644
--- a/Utilities/cmcurl/lib/curl_sspi.c
+++ b/Utilities/cmcurl/lib/curl_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_sspi.h b/Utilities/cmcurl/lib/curl_sspi.h
index 881384d4e..ad111309c 100644
--- a/Utilities/cmcurl/lib/curl_sspi.h
+++ b/Utilities/cmcurl/lib/curl_sspi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index 414614401..eb8e13608 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/lib/curl_threads.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index e10b7a1b0..63392f671 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/curlx.h b/Utilities/cmcurl/lib/curlx.h
index 9f21f60d5..1796afa00 100644
--- a/Utilities/cmcurl/lib/curlx.h
+++ b/Utilities/cmcurl/lib/curlx.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index e23e66191..6f7678f5c 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/dict.h b/Utilities/cmcurl/lib/dict.h
index 6a6c772d1..b283a0dfc 100644
--- a/Utilities/cmcurl/lib/dict.h
+++ b/Utilities/cmcurl/lib/dict.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_DICT
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 4aef8b266..3b1d5d60e 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -69,12 +71,6 @@ static const char *doh_strerror(DOHcode code)
}
#endif
-#ifdef DEBUGBUILD
-#define UNITTEST
-#else
-#define UNITTEST static
-#endif
-
/* @unittest 1655
*/
UNITTEST DOHcode doh_encode(const char *host,
@@ -247,6 +243,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
+ ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
@@ -306,14 +303,6 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
if(data->set.ssl.certinfo)
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
- if(data->set.str[STRING_SSL_RANDOM_FILE]) {
- ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE,
- data->set.str[STRING_SSL_RANDOM_FILE]);
- }
- if(data->set.str[STRING_SSL_EGDSOCKET]) {
- ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET,
- data->set.str[STRING_SSL_EGDSOCKET]);
- }
if(data->set.ssl.fsslctx)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
@@ -407,7 +396,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
goto error;
dohp->pending++;
- if(Curl_ipv6works(data)) {
+ if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
@@ -803,7 +792,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
#endif
CURLcode result = CURLE_OK;
int i;
- size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
+ size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
if(!de)
/* no input == no output! */
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
index 70e96e012..678e807fe 100644
--- a/Utilities/cmcurl/lib/doh.h
+++ b/Utilities/cmcurl/lib/doh.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "urldata.h"
@@ -27,21 +29,6 @@
#ifndef CURL_DISABLE_DOH
-/*
- * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
- * and returns a 'Curl_addrinfo *' with the address information.
- */
-
-struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp);
-
-CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **dns);
-
-int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
-
typedef enum {
DOH_OK,
DOH_DNS_BAD_LABEL, /* 1 */
@@ -67,6 +54,38 @@ typedef enum {
DNS_TYPE_DNAME = 39 /* RFC6672 */
} DNStype;
+/* one of these for each DoH request */
+struct dnsprobe {
+ CURL *easy;
+ DNStype dnstype;
+ unsigned char dohbuffer[512];
+ size_t dohlen;
+ struct dynbuf serverdoh;
+};
+
+struct dohdata {
+ struct curl_slist *headers;
+ struct dnsprobe probe[DOH_PROBE_SLOTS];
+ unsigned int pending; /* still outstanding requests */
+ int port;
+ const char *host;
+};
+
+/*
+ * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
+ * and returns a 'Curl_addrinfo *' with the address information.
+ */
+
+struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry **dns);
+
+int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
+
#define DOH_MAX_ADDR 24
#define DOH_MAX_CNAME 4
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
deleted file mode 100644
index 73ef2fa72..000000000
--- a/Utilities/cmcurl/lib/dotdot.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#include <curl/curl.h>
-
-#include "dotdot.h"
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/*
- * "Remove Dot Segments"
- * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
- */
-
-/*
- * Curl_dedotdotify()
- * @unittest: 1395
- *
- * This function gets a null-terminated path with dot and dotdot sequences
- * passed in and strips them off according to the rules in RFC 3986 section
- * 5.2.4.
- *
- * The function handles a query part ('?' + stuff) appended but it expects
- * that fragments ('#' + stuff) have already been cut off.
- *
- * RETURNS
- *
- * an allocated dedotdotified output string
- */
-char *Curl_dedotdotify(const char *input)
-{
- size_t inlen = strlen(input);
- char *clone;
- size_t clen = inlen; /* the length of the cloned input */
- char *out = malloc(inlen + 1);
- char *outptr;
- char *orgclone;
- char *queryp;
- if(!out)
- return NULL; /* out of memory */
-
- *out = 0; /* null-terminates, for inputs like "./" */
-
- /* get a cloned copy of the input */
- clone = strdup(input);
- if(!clone) {
- free(out);
- return NULL;
- }
- orgclone = clone;
- outptr = out;
-
- if(!*clone) {
- /* zero length string, return that */
- free(out);
- return clone;
- }
-
- /*
- * To handle query-parts properly, we must find it and remove it during the
- * dotdot-operation and then append it again at the end to the output
- * string.
- */
- queryp = strchr(clone, '?');
- if(queryp)
- *queryp = 0;
-
- do {
-
- /* A. If the input buffer begins with a prefix of "../" or "./", then
- remove that prefix from the input buffer; otherwise, */
-
- if(!strncmp("./", clone, 2)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strncmp("../", clone, 3)) {
- clone += 3;
- clen -= 3;
- }
-
- /* B. if the input buffer begins with a prefix of "/./" or "/.", where
- "." is a complete path segment, then replace that prefix with "/" in
- the input buffer; otherwise, */
- else if(!strncmp("/./", clone, 3)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strcmp("/.", clone)) {
- clone[1]='/';
- clone++;
- clen -= 1;
- }
-
- /* C. if the input buffer begins with a prefix of "/../" or "/..", where
- ".." is a complete path segment, then replace that prefix with "/" in
- the input buffer and remove the last segment and its preceding "/" (if
- any) from the output buffer; otherwise, */
-
- else if(!strncmp("/../", clone, 4)) {
- clone += 3;
- clen -= 3;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
- else if(!strcmp("/..", clone)) {
- clone[2]='/';
- clone += 2;
- clen -= 2;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
-
- /* D. if the input buffer consists only of "." or "..", then remove
- that from the input buffer; otherwise, */
-
- else if(!strcmp(".", clone) || !strcmp("..", clone)) {
- *clone = 0;
- *out = 0;
- }
-
- else {
- /* E. move the first path segment in the input buffer to the end of
- the output buffer, including the initial "/" character (if any) and
- any subsequent characters up to, but not including, the next "/"
- character or the end of the input buffer. */
-
- do {
- *outptr++ = *clone++;
- clen--;
- } while(*clone && (*clone != '/'));
- *outptr = 0;
- }
-
- } while(*clone);
-
- if(queryp) {
- size_t qlen;
- /* There was a query part, append that to the output. The 'clone' string
- may now have been altered so we copy from the original input string
- from the correct index. */
- size_t oindex = queryp - orgclone;
- qlen = strlen(&input[oindex]);
- memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
- }
-
- free(orgclone);
- return out;
-}
diff --git a/Utilities/cmcurl/lib/dynbuf.c b/Utilities/cmcurl/lib/dynbuf.c
index ada7e0ccf..0b1cf9afd 100644
--- a/Utilities/cmcurl/lib/dynbuf.c
+++ b/Utilities/cmcurl/lib/dynbuf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -126,7 +128,6 @@ void Curl_dyn_reset(struct dynbuf *s)
s->leng = 0;
}
-#ifdef USE_NGTCP2
/*
* Specify the size of the tail to keep (number of bytes from the end of the
* buffer). The rest will be dropped.
@@ -151,7 +152,6 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
return CURLE_OK;
}
-#endif
/*
* Appends a buffer with length.
@@ -253,3 +253,18 @@ size_t Curl_dyn_len(const struct dynbuf *s)
DEBUGASSERT(!s->leng || s->bufr);
return s->leng;
}
+
+/*
+ * Set a new (smaller) length.
+ */
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ if(set > s->leng)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ s->leng = set;
+ s->bufr[s->leng] = 0;
+ return CURLE_OK;
+}
diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h
index 252411f84..04a728c77 100644
--- a/Utilities/cmcurl/lib/dynbuf.h
+++ b/Utilities/cmcurl/lib/dynbuf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,8 +20,12 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
+#include <curl/curl.h>
+
#ifndef BUILDING_LIBCURL
/* this renames the functions so that the tool code can use the same code
without getting symbol collisions */
@@ -36,12 +40,13 @@
#define Curl_dyn_len(a) curlx_dyn_len(a)
#define Curl_dyn_reset(a) curlx_dyn_reset(a)
#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
+#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
#define curlx_dynbuf dynbuf /* for the struct name */
#endif
struct dynbuf {
char *bufr; /* point to a null-terminated allocated buffer */
- size_t leng; /* number of bytes *EXCLUDING* the zero terminator */
+ size_t leng; /* number of bytes *EXCLUDING* the null-terminator */
size_t allc; /* size of the current allocation */
size_t toobig; /* size limit for the buffer */
#ifdef DEBUGBUILD
@@ -61,6 +66,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
WARN_UNUSED_RESULT;
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
char *Curl_dyn_ptr(const struct dynbuf *s);
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
size_t Curl_dyn_len(const struct dynbuf *s);
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index bd9d695bb..b8ac1ef8a 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -80,6 +82,8 @@
#include "altsvc.h"
#include "hsts.h"
+#include "easy_lock.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -89,6 +93,19 @@
static unsigned int initialized;
static long init_flags;
+#ifdef GLOBAL_INIT_IS_THREADSAFE
+
+static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
+#define global_init_lock() curl_simple_lock_lock(&s_lock)
+#define global_init_unlock() curl_simple_lock_unlock(&s_lock)
+
+#else
+
+#define global_init_lock()
+#define global_init_unlock()
+
+#endif
+
/*
* strdup (and other memory functions) is redefined in complicated
* ways, but at this point it must be defined as the system-supplied strdup
@@ -161,7 +178,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
#endif
#ifdef __AMIGA__
- if(!Curl_amiga_init()) {
+ if(Curl_amiga_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
goto fail;
}
@@ -207,7 +224,14 @@ static CURLcode global_init(long flags, bool memoryfuncs)
*/
CURLcode curl_global_init(long flags)
{
- return global_init(flags, TRUE);
+ CURLcode result;
+ global_init_lock();
+
+ result = global_init(flags, TRUE);
+
+ global_init_unlock();
+
+ return result;
}
/*
@@ -218,15 +242,20 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
curl_free_callback f, curl_realloc_callback r,
curl_strdup_callback s, curl_calloc_callback c)
{
+ CURLcode result;
+
/* Invalid input, return immediately */
if(!m || !f || !r || !s || !c)
return CURLE_FAILED_INIT;
+ global_init_lock();
+
if(initialized) {
/* Already initialized, don't do it again, but bump the variable anyway to
work like curl_global_init() and require the same amount of cleanup
calls. */
initialized++;
+ global_init_unlock();
return CURLE_OK;
}
@@ -239,7 +268,11 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
Curl_ccalloc = c;
/* Call the actual init function, but without setting */
- return global_init(flags, FALSE);
+ result = global_init(flags, FALSE);
+
+ global_init_unlock();
+
+ return result;
}
/**
@@ -248,11 +281,17 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
*/
void curl_global_cleanup(void)
{
- if(!initialized)
+ global_init_lock();
+
+ if(!initialized) {
+ global_init_unlock();
return;
+ }
- if(--initialized)
+ if(--initialized) {
+ global_init_unlock();
return;
+ }
Curl_ssl_cleanup();
Curl_resolver_global_cleanup();
@@ -273,6 +312,25 @@ void curl_global_cleanup(void)
#endif
init_flags = 0;
+
+ global_init_unlock();
+}
+
+/*
+ * curl_global_sslset() globally initializes the SSL backend to use.
+ */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ CURLsslset rc;
+
+ global_init_lock();
+
+ rc = Curl_init_sslset_nolock(id, name, avail);
+
+ global_init_unlock();
+
+ return rc;
}
/*
@@ -285,14 +343,18 @@ struct Curl_easy *curl_easy_init(void)
struct Curl_easy *data;
/* Make sure we inited the global SSL stuff */
+ global_init_lock();
+
if(!initialized) {
- result = curl_global_init(CURL_GLOBAL_DEFAULT);
+ result = global_init(CURL_GLOBAL_DEFAULT, TRUE);
if(result) {
/* something in the global init failed, return nothing */
DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
+ global_init_unlock();
return NULL;
}
}
+ global_init_unlock();
/* We use curl_open() with undefined URL so far */
result = Curl_open(&data);
@@ -507,19 +569,23 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
/* wait for activity or timeout */
pollrc = Curl_poll(fds, numfds, ev->ms);
+ if(pollrc < 0)
+ return CURLE_UNRECOVERABLE_POLL;
after = Curl_now();
ev->msbump = FALSE; /* reset here */
- if(0 == pollrc) {
+ if(!pollrc) {
/* timeout! */
ev->ms = 0;
/* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
&ev->running_handles);
}
- else if(pollrc > 0) {
+ else {
+ /* here pollrc is > 0 */
+
/* loop over the monitored sockets to see which ones had activity */
for(i = 0; i< numfds; i++) {
if(fds[i].revents) {
@@ -545,8 +611,6 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
}
}
}
- else
- return CURLE_RECV_ERROR;
if(mcode)
return CURLE_URL_MALFORMAT;
@@ -662,7 +726,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
else {
/* this multi handle will only ever have a single easy handled attached
to it, so make it use minimal hashes */
- multi = Curl_multi_handle(1, 3);
+ multi = Curl_multi_handle(1, 3, 7);
if(!multi)
return CURLE_OUT_OF_MEMORY;
data->multi_easy = multi;
@@ -838,6 +902,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
+#ifndef CURL_DISABLE_COOKIES
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
@@ -856,6 +921,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
if(!outcurl->state.cookielist)
goto fail;
}
+#endif
if(data->state.url) {
outcurl->state.url = strdup(data->state.url);
@@ -878,7 +944,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
goto fail;
}
-#ifdef USE_ALTSVC
+#ifndef CURL_DISABLE_ALTSVC
if(data->asi) {
outcurl->asi = Curl_altsvc_init();
if(!outcurl->asi)
@@ -937,8 +1003,10 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
fail:
if(outcurl) {
+#ifndef CURL_DISABLE_COOKIES
curl_slist_free_all(outcurl->state.cookielist);
outcurl->state.cookielist = NULL;
+#endif
Curl_safefree(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
Curl_safefree(outcurl->state.url);
@@ -1065,6 +1133,16 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
}
}
+#ifdef USE_HYPER
+ if(!(newstate & KEEP_SEND_PAUSE)) {
+ /* need to wake the send body waker */
+ if(data->hyp.send_body_waker) {
+ hyper_waker_wake(data->hyp.send_body_waker);
+ data->hyp.send_body_waker = NULL;
+ }
+ }
+#endif
+
/* if there's no error and we're not pausing both directions, we want
to have this handle checked soon */
if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
@@ -1093,8 +1171,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
}
-static CURLcode easy_connection(struct Curl_easy *data,
- curl_socket_t *sfd,
+static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
struct connectdata **connp)
{
if(!data)
@@ -1153,11 +1230,12 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
}
/*
- * Sends data over the connected socket. Use after successful
- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ * Sends data over the connected socket.
+ *
+ * This is the private internal version of curl_easy_send()
*/
-CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
- size_t buflen, size_t *n)
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n)
{
curl_socket_t sfd;
CURLcode result;
@@ -1165,9 +1243,6 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
struct connectdata *c = NULL;
SIGPIPE_VARIABLE(pipe_st);
- if(Curl_is_in_callback(data))
- return CURLE_RECURSIVE_API_CALL;
-
result = easy_connection(data, &sfd, &c);
if(result)
return result;
@@ -1189,8 +1264,25 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
if(!result && !n1)
return CURLE_AGAIN;
- *n = (size_t)n1;
+ *n = n1;
+
+ return result;
+}
+
+/*
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
+ size_t buflen, size_t *n)
+{
+ ssize_t written = 0;
+ CURLcode result;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+ result = Curl_senddata(data, buffer, buflen, &written);
+ *n = (size_t)written;
return result;
}
diff --git a/Utilities/cmcurl/lib/easy_lock.h b/Utilities/cmcurl/lib/easy_lock.h
new file mode 100644
index 000000000..d96e56b8d
--- /dev/null
+++ b/Utilities/cmcurl/lib/easy_lock.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#define GLOBAL_INIT_IS_THREADSAFE
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+
+#ifdef __MINGW32__
+#ifndef __MINGW64_VERSION_MAJOR
+#if (__MINGW32_MAJOR_VERSION < 5) || \
+ (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
+/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
+typedef PVOID SRWLOCK, *PSRWLOCK;
+#endif
+#endif
+#ifndef SRWLOCK_INIT
+#define SRWLOCK_INIT NULL
+#endif
+#endif /* __MINGW32__ */
+
+#define curl_simple_lock SRWLOCK
+#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
+
+#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
+#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
+
+#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
+#include <stdatomic.h>
+#if defined(HAVE_SCHED_YIELD)
+#include <sched.h>
+#endif
+
+#define curl_simple_lock atomic_int
+#define CURL_SIMPLE_LOCK_INIT 0
+
+/* a clang-thing */
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifndef __INTEL_COMPILER
+/* The Intel compiler tries to look like GCC *and* clang *and* lies in its
+ __has_builtin() function, so override it. */
+
+/* if GCC on i386/x86_64 or if the built-in is present */
+#if ( (defined(__GNUC__) && !defined(__clang__)) && \
+ (defined(__i386__) || defined(__x86_64__))) || \
+ __has_builtin(__builtin_ia32_pause)
+#define HAVE_BUILTIN_IA32_PAUSE
+#endif
+
+#endif
+
+static inline void curl_simple_lock_lock(curl_simple_lock *lock)
+{
+ for(;;) {
+ if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
+ break;
+ /* Reduce cache coherency traffic */
+ while(atomic_load_explicit(lock, memory_order_relaxed)) {
+ /* Reduce load (not mandatory) */
+#ifdef HAVE_BUILTIN_IA32_PAUSE
+ __builtin_ia32_pause();
+#elif defined(__aarch64__)
+ __asm__ volatile("yield" ::: "memory");
+#elif defined(HAVE_SCHED_YIELD)
+ sched_yield();
+#endif
+ }
+ }
+}
+
+static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
+{
+ atomic_store_explicit(lock, false, memory_order_release);
+}
+
+#else
+
+#undef GLOBAL_INIT_IS_THREADSAFE
+
+#endif
diff --git a/Utilities/cmcurl/lib/easygetopt.c b/Utilities/cmcurl/lib/easygetopt.c
index 7b2213fb2..a639bb375 100644
--- a/Utilities/cmcurl/lib/easygetopt.c
+++ b/Utilities/cmcurl/lib/easygetopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* ___|___/|_| ______|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/easyif.h b/Utilities/cmcurl/lib/easyif.h
index 336441828..205382cd0 100644
--- a/Utilities/cmcurl/lib/easyif.h
+++ b/Utilities/cmcurl/lib/easyif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,11 +20,16 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
* Prototypes for library-wide functions provided by easy.c
*/
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n);
+
#ifdef CURLDEBUG
CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy);
#endif
diff --git a/Utilities/cmcurl/lib/easyoptions.c b/Utilities/cmcurl/lib/easyoptions.c
index 04871ad1e..e59b63af7 100644
--- a/Utilities/cmcurl/lib/easyoptions.c
+++ b/Utilities/cmcurl/lib/easyoptions.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* ___|___/|_| ______|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* This source code is generated by optiontable.pl - DO NOT EDIT BY HAND */
@@ -105,7 +107,8 @@ struct curl_easyoption Curl_easyopts[] = {
{"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS,
CURLOT_LONG, 0},
{"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0},
- {"FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOT_LONG, 0},
+ {"FTP_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT,
+ CURLOT_LONG, CURLOT_FLAG_ALIAS},
{"FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP, CURLOT_LONG, 0},
{"FTP_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, CURLOT_FLAG_ALIAS},
{"FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC, CURLOT_LONG, 0},
@@ -201,6 +204,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
{"PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0},
{"PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0},
+ {"PROTOCOLS_STR", CURLOPT_PROTOCOLS_STR, CURLOT_STRING, 0},
{"PROXY", CURLOPT_PROXY, CURLOT_STRING, 0},
{"PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0},
{"PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0},
@@ -243,6 +247,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0},
{"READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0},
{"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0},
+ {"REDIR_PROTOCOLS_STR", CURLOPT_REDIR_PROTOCOLS_STR, CURLOT_STRING, 0},
{"REFERER", CURLOPT_REFERER, CURLOT_STRING, 0},
{"REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0},
{"RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0},
@@ -262,8 +267,8 @@ struct curl_easyoption Curl_easyopts[] = {
{"SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0},
{"SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0},
{"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
- {"SERVER_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT,
- CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"SERVER_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT,
+ CURLOT_LONG, 0},
{"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
{"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
{"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
@@ -273,6 +278,8 @@ struct curl_easyoption Curl_easyopts[] = {
{"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOT_STRING, 0},
{"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0},
{"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0},
+ {"SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0},
+ {"SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, CURLOT_FUNCTION, 0},
{"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
CURLOT_STRING, 0},
{"SSH_HOST_PUBLIC_KEY_SHA256", CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
@@ -347,10 +354,11 @@ struct curl_easyoption Curl_easyopts[] = {
{"WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0},
{"WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0},
{"WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"WS_OPTIONS", CURLOPT_WS_OPTIONS, CURLOT_LONG, 0},
{"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0},
{"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0},
{"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0},
- {NULL, CURLOPT_LASTENTRY, 0, 0} /* end of table */
+ {NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0} /* end of table */
};
#ifdef DEBUGBUILD
@@ -360,6 +368,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (315 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (320 + 1));
}
#endif
diff --git a/Utilities/cmcurl/lib/easyoptions.h b/Utilities/cmcurl/lib/easyoptions.h
index 91e11908b..33f816d6b 100644
--- a/Utilities/cmcurl/lib/easyoptions.h
+++ b/Utilities/cmcurl/lib/easyoptions.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* should probably go into the public header */
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index ff5887508..da7e5524f 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* Escape and unescape URL encoding in strings. The functions return a new
@@ -75,6 +77,9 @@ char *curl_unescape(const char *string, int length)
return curl_easy_unescape(NULL, string, length, NULL);
}
+/* Escapes for URL the given unescaped string of given length.
+ * 'data' is ignored since 7.82.0.
+ */
char *curl_easy_escape(struct Curl_easy *data, const char *string,
int inlength)
{
@@ -116,8 +121,6 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
* Returns a pointer to a malloced string in *ostring with length given in
* *olen. If length == 0, the length is assumed to be strlen(string).
*
- * 'data' can be set to NULL
- *
* ctrl options:
* - REJECT_NADA: accept everything
* - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
@@ -191,6 +194,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
* pointer to a malloced string with length given in *olen.
* If length == 0, the length is assumed to be strlen(string).
* If olen == NULL, no output length is stored.
+ * 'data' is ignored since 7.82.0.
*/
char *curl_easy_unescape(struct Curl_easy *data, const char *string,
int length, int *olen)
diff --git a/Utilities/cmcurl/lib/escape.h b/Utilities/cmcurl/lib/escape.h
index 02668835c..61d4611bf 100644
--- a/Utilities/cmcurl/lib/escape.h
+++ b/Utilities/cmcurl/lib/escape.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 3da79a2c1..d82d57b46 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -69,6 +71,8 @@
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
+#elif defined(__amigaos4__)
+#define AMIGA_FILESYSTEM 1
#endif
#ifdef OPEN_NEEDS_ARG3
@@ -194,8 +198,33 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
return CURLE_URL_MALFORMAT;
}
+ #ifdef AMIGA_FILESYSTEM
+ /*
+ * A leading slash in an AmigaDOS path denotes the parent
+ * directory, and hence we block this as it is relative.
+ * Absolute paths start with 'volumename:', so we check for
+ * this first. Failing that, we treat the path as a real unix
+ * path, but only if the application was compiled with -lunix.
+ */
+ fd = -1;
+ file->path = real_path;
+
+ if(real_path[0] == '/') {
+ extern int __unix_path_semantics;
+ if(strchr(real_path + 1, ':')) {
+ /* Amiga absolute path */
+ fd = open_readonly(real_path + 1, O_RDONLY);
+ file->path++;
+ }
+ else if(__unix_path_semantics) {
+ /* -lunix fallback */
+ fd = open_readonly(real_path, O_RDONLY);
+ }
+ }
+ #else
fd = open_readonly(real_path, O_RDONLY);
file->path = real_path;
+ #endif
#endif
file->freepath = real_path; /* free this when done */
@@ -234,7 +263,7 @@ static CURLcode file_disconnect(struct Curl_easy *data,
{
(void)dead_connection; /* not used */
(void)conn;
- return file_done(data, 0, 0);
+ return file_done(data, CURLE_OK, FALSE);
}
#ifdef DOS_FILESYSTEM
diff --git a/Utilities/cmcurl/lib/file.h b/Utilities/cmcurl/lib/file.h
index 338f92e46..826d45380 100644
--- a/Utilities/cmcurl/lib/file.h
+++ b/Utilities/cmcurl/lib/file.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index b7e9f0f5e..7bbf24bde 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index 5ae23ad4a..5bad718cc 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
diff --git a/Utilities/cmcurl/lib/fopen.c b/Utilities/cmcurl/lib/fopen.c
new file mode 100644
index 000000000..ad3691ba9
--- /dev/null
+++ b/Utilities/cmcurl/lib/fopen.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+ !defined(CURL_DISABLE_HSTS)
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "urldata.h"
+#include "rand.h"
+#include "fopen.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * Curl_fopen() opens a file for writing with a temp name, to be renamed
+ * to the final name when completed. If there is an existing file using this
+ * name at the time of the open, this function will clone the mode from that
+ * file. if 'tempname' is non-NULL, it needs a rename after the file is
+ * written.
+ */
+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
+ FILE **fh, char **tempname)
+{
+ CURLcode result = CURLE_WRITE_ERROR;
+ unsigned char randsuffix[9];
+ char *tempstore = NULL;
+ struct_stat sb;
+ int fd = -1;
+ *tempname = NULL;
+
+ if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
+ /* a non-regular file, fallback to direct fopen() */
+ *fh = fopen(filename, FOPEN_WRITETEXT);
+ if(*fh)
+ return CURLE_OK;
+ goto fail;
+ }
+
+ result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
+ if(result)
+ goto fail;
+
+ tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+ if(!tempstore) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ result = CURLE_WRITE_ERROR;
+ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if(fd == -1)
+ goto fail;
+
+#ifdef HAVE_FCHMOD
+ {
+ struct_stat nsb;
+ if((fstat(fd, &nsb) != -1) &&
+ (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
+ /* if the user and group are the same, clone the original mode */
+ if(fchmod(fd, sb.st_mode) == -1)
+ goto fail;
+ }
+ }
+#endif
+
+ *fh = fdopen(fd, FOPEN_WRITETEXT);
+ if(!*fh)
+ goto fail;
+
+ *tempname = tempstore;
+ return CURLE_OK;
+
+fail:
+ if(fd != -1) {
+ close(fd);
+ unlink(tempstore);
+ }
+
+ free(tempstore);
+
+ *tempname = NULL;
+ return result;
+}
+
+#endif /* ! disabled */
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.h b/Utilities/cmcurl/lib/fopen.h
index 7b6ac489a..289e55f2a 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.h
+++ b/Utilities/cmcurl/lib/fopen.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_WOLFSSH_H
-#define HEADER_CURL_WOLFSSH_H
+#ifndef HEADER_CURL_FOPEN_H
+#define HEADER_CURL_FOPEN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,8 +20,11 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
-extern const struct Curl_handler Curl_handler_sftp;
+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
+ FILE **fh, char **tempname);
-#endif /* HEADER_CURL_WOLFSSH_H */
+#endif
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 5fefd7a6e..46542b432 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -249,8 +251,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
}
}
else {
- /* This is not array-state, get next option */
- option = va_arg(params, CURLformoption);
+ /* This is not array-state, get next option. This gets an 'int' with
+ va_arg() because CURLformoption might be a smaller type than int and
+ might cause compiler warnings and wrong behavior. */
+ option = (CURLformoption)va_arg(params, int);
if(CURLFORM_END == option)
break;
}
diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index 09c6e9c28..c6c6397cd 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 45d9cedc3..d02ab99e9 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -514,10 +516,9 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
}
else {
/* Add timeout to multi handle and break out of the loop */
- if(*connected == FALSE) {
- Curl_expire(data, data->set.accepttimeout > 0 ?
- data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
- }
+ Curl_expire(data, data->set.accepttimeout ?
+ data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
+ EXPIRE_FTP_ACCEPT);
}
return result;
@@ -783,8 +784,9 @@ static CURLcode ftp_state_user(struct Curl_easy *data,
&conn->proto.ftpc.pp, "USER %s",
conn->user?conn->user:"");
if(!result) {
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ ftpc->ftp_trying_alternative = FALSE;
state(data, FTP_USER);
- data->state.ftp_trying_alternative = FALSE;
}
return result;
}
@@ -2127,9 +2129,11 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
default:
infof(data, "unsupported MDTM reply format");
break;
- case 550: /* "No such file or directory" */
- failf(data, "Given file does not exist");
- result = CURLE_REMOTE_FILE_NOT_FOUND;
+ case 550: /* 550 is used for several different problems, e.g.
+ "No such file or directory" or "Permission denied".
+ It does not mean that the file does not exist at all. */
+ infof(data, "MDTM failed: file does not exist or permission problem,"
+ " continuing");
break;
}
@@ -2622,13 +2626,13 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
(the server denies to log the specified user) */
if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
- !data->state.ftp_trying_alternative) {
+ !ftpc->ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
result =
Curl_pp_sendf(data, &ftpc->pp, "%s",
data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
if(!result) {
- data->state.ftp_trying_alternative = TRUE;
+ ftpc->ftp_trying_alternative = TRUE;
state(data, FTP_USER);
}
}
@@ -2701,10 +2705,11 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
set a valid level */
Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
- if(Curl_sec_login(data, conn))
- infof(data, "Logging in with password in cleartext");
- else
- infof(data, "Authentication successful");
+ if(Curl_sec_login(data, conn)) {
+ failf(data, "secure login failed");
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+ infof(data, "Authentication successful");
}
#endif
@@ -3561,8 +3566,10 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
bool connected = FALSE;
bool complete = FALSE;
- /* the ftp struct is inited in ftp_connect() */
- struct FTP *ftp = data->req.p.ftp;
+ /* the ftp struct is inited in ftp_connect(). If we are connecting to an HTTP
+ * proxy then the state will not be valid until after that connection is
+ * complete */
+ struct FTP *ftp = NULL;
/* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
@@ -3603,6 +3610,9 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
return result;
#endif
+ /* Curl_proxy_connect might have moved the protocol state */
+ ftp = data->req.p.ftp;
+
if(ftpc->state) {
/* already in a state so skip the initial commands.
They are only done to kickstart the do_more state */
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index 1cfdac085..7f6f4328d 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,8 +20,12 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
+#include "curl_setup.h"
+
#include "pingpong.h"
#ifndef CURL_DISABLE_FTP
@@ -149,6 +153,7 @@ struct ftp_conn {
curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set
it */
+ BIT(ftp_trying_alternative);
};
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index 716ff3817..40f5f3f18 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/**
@@ -420,7 +422,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
char *endptr = finfo->b_data + 6;
/* here we can deal with directory size, pass the leading
whitespace and then the digits */
- while(ISSPACE(*endptr))
+ while(ISBLANK(*endptr))
endptr++;
while(ISDIGIT(*endptr))
endptr++;
@@ -892,7 +894,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->item_length++;
switch(parser->state.NT.sub.time) {
case PL_WINNT_TIME_PRESPACE:
- if(!ISSPACE(c)) {
+ if(!ISBLANK(c)) {
parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
}
break;
diff --git a/Utilities/cmcurl/lib/ftplistparser.h b/Utilities/cmcurl/lib/ftplistparser.h
index e4cd8201d..0a8054341 100644
--- a/Utilities/cmcurl/lib/ftplistparser.h
+++ b/Utilities/cmcurl/lib/ftplistparser.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/functypes.h b/Utilities/cmcurl/lib/functypes.h
new file mode 100644
index 000000000..8891b1d5d
--- /dev/null
+++ b/Utilities/cmcurl/lib/functypes.h
@@ -0,0 +1,115 @@
+#ifndef HEADER_CURL_FUNCTYPES_H
+#define HEADER_CURL_FUNCTYPES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/* defaults:
+
+ ssize_t recv(int, void *, size_t, int);
+ ssize_t send(int, const void *, size_t, int);
+
+ If other argument or return types are needed:
+
+ 1. For systems that run configure or cmake, the alternatives are provided
+ here.
+ 2. For systems with config-*.h files, define them there.
+*/
+
+#ifdef WIN32
+/* int recv(SOCKET, char *, int, int) */
+#define RECV_TYPE_ARG1 SOCKET
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 int
+#define RECV_TYPE_RETV int
+
+/* int send(SOCKET, const char *, int, int); */
+#define SEND_TYPE_ARG1 SOCKET
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+
+#elif defined(__AMIGA__) /* Any AmigaOS flavour */
+
+/* long recv(long, char *, long, long); */
+#define RECV_TYPE_ARG1 long
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 long
+#define RECV_TYPE_ARG4 long
+#define RECV_TYPE_RETV long
+
+/* int send(int, const char *, int, int); */
+#define SEND_TYPE_ARG1 int
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+#endif
+
+
+#ifndef RECV_TYPE_ARG1
+#define RECV_TYPE_ARG1 int
+#endif
+
+#ifndef RECV_TYPE_ARG2
+#define RECV_TYPE_ARG2 void *
+#endif
+
+#ifndef RECV_TYPE_ARG3
+#define RECV_TYPE_ARG3 size_t
+#endif
+
+#ifndef RECV_TYPE_ARG4
+#define RECV_TYPE_ARG4 int
+#endif
+
+#ifndef RECV_TYPE_RETV
+#define RECV_TYPE_RETV ssize_t
+#endif
+
+#ifndef SEND_QUAL_ARG2
+#define SEND_QUAL_ARG2 const
+#endif
+
+#ifndef SEND_TYPE_ARG1
+#define SEND_TYPE_ARG1 int
+#endif
+
+#ifndef SEND_TYPE_ARG2
+#define SEND_TYPE_ARG2 void *
+#endif
+
+#ifndef SEND_TYPE_ARG3
+#define SEND_TYPE_ARG3 size_t
+#endif
+
+#ifndef SEND_TYPE_ARG4
+#define SEND_TYPE_ARG4 int
+#endif
+
+#ifndef SEND_TYPE_RETV
+#define SEND_TYPE_RETV ssize_t
+#endif
+
+#endif /* HEADER_CURL_FUNCTYPES_H */
diff --git a/Utilities/cmcurl/lib/getenv.c b/Utilities/cmcurl/lib/getenv.c
index 92c53505c..5f00fd13a 100644
--- a/Utilities/cmcurl/lib/getenv.c
+++ b/Utilities/cmcurl/lib/getenv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 9091e6139..c3556b310 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -164,6 +166,20 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
case CURLINFO_SCHEME:
*param_charp = data->info.conn_scheme;
break;
+ case CURLINFO_CAPATH:
+#ifdef CURL_CA_PATH
+ *param_charp = CURL_CA_PATH;
+#else
+ *param_charp = NULL;
+#endif
+ break;
+ case CURLINFO_CAINFO:
+#ifdef CURL_CA_BUNDLE
+ *param_charp = CURL_CA_BUNDLE;
+#else
+ *param_charp = NULL;
+#endif
+ break;
default:
return CURLE_UNKNOWN_OPTION;
@@ -285,6 +301,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
/* return if the condition prevented the document to get transferred */
*param_longp = data->info.timecond ? 1L : 0L;
break;
+#ifndef CURL_DISABLE_RTSP
case CURLINFO_RTSP_CLIENT_CSEQ:
*param_longp = data->state.rtsp_next_client_CSeq;
break;
@@ -294,6 +311,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
case CURLINFO_RTSP_CSEQ_RECV:
*param_longp = data->state.rtsp_CSeq_recv;
break;
+#endif
case CURLINFO_HTTP_VERSION:
switch(data->info.httpversion) {
case 10:
@@ -560,7 +578,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
CURLcode result = CURLE_UNKNOWN_OPTION;
if(!data)
- return result;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, info);
diff --git a/Utilities/cmcurl/lib/getinfo.h b/Utilities/cmcurl/lib/getinfo.h
index f35d1b4b3..1b5e8c20f 100644
--- a/Utilities/cmcurl/lib/getinfo.h
+++ b/Utilities/cmcurl/lib/getinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...);
CURLcode Curl_initinfo(struct Curl_easy *data);
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index 0a3ba8fb5..01f4bdef0 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/gopher.h b/Utilities/cmcurl/lib/gopher.h
index 6b8bd554a..4ea269d2b 100644
--- a/Utilities/cmcurl/lib/gopher.h
+++ b/Utilities/cmcurl/lib/gopher.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_GOPHER
diff --git a/Utilities/cmcurl/lib/h2h3.c b/Utilities/cmcurl/lib/h2h3.c
index c0ed58d37..50254ad0f 100644
--- a/Utilities/cmcurl/lib/h2h3.c
+++ b/Utilities/cmcurl/lib/h2h3.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -189,7 +191,7 @@ CURLcode Curl_pseudo_headers(struct Curl_easy *data,
vptr = Curl_checkheaders(data, STRCONST(H2H3_PSEUDO_SCHEME));
if(vptr) {
vptr += sizeof(H2H3_PSEUDO_SCHEME);
- while(*vptr && ISSPACE(*vptr))
+ while(*vptr && ISBLANK(*vptr))
vptr++;
nva[2].value = vptr;
infof(data, "set pseudo header %s to %s", H2H3_PSEUDO_SCHEME, vptr);
@@ -256,9 +258,6 @@ CURLcode Curl_pseudo_headers(struct Curl_easy *data,
nva[i].valuelen = (end - hdbuf);
}
- nva[i].value = hdbuf;
- nva[i].valuelen = (end - hdbuf);
-
++i;
}
diff --git a/Utilities/cmcurl/lib/h2h3.h b/Utilities/cmcurl/lib/h2h3.h
index 22256841c..84caec5d5 100644
--- a/Utilities/cmcurl/lib/h2h3.h
+++ b/Utilities/cmcurl/lib/h2h3.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 884890694..b6a2a33c7 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index e166916a9..5b59bf111 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/headers.c b/Utilities/cmcurl/lib/headers.c
index 226c696be..978c918f4 100644
--- a/Utilities/cmcurl/lib/headers.c
+++ b/Utilities/cmcurl/lib/headers.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -32,7 +34,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HEADERS_API)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
/* Generate the curl_header struct for the user. This function MUST assign all
struct fields in the output struct. */
@@ -72,8 +74,8 @@ CURLHcode curl_easy_header(CURL *easy,
struct Curl_header_store *hs = NULL;
struct Curl_header_store *pick = NULL;
if(!name || !hout || !data ||
- (type > (CURLH_HEADER|CURLH_TRAILER|CURLH_CONNECT|CURLH_1XX)) ||
- !type || (request < -1))
+ (type > (CURLH_HEADER|CURLH_TRAILER|CURLH_CONNECT|CURLH_1XX|
+ CURLH_PSEUDO)) || !type || (request < -1))
return CURLHE_BAD_ARGUMENT;
if(!Curl_llist_count(&data->state.httphdrs))
return CURLHE_NOHEADERS; /* no headers available */
@@ -205,7 +207,7 @@ static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
return CURLE_BAD_FUNCTION_ARGUMENT;
/* skip all leading space letters */
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
*value = header;
@@ -216,6 +218,57 @@ static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
return CURLE_OK;
}
+static CURLcode unfold_value(struct Curl_easy *data, const char *value,
+ size_t vlen) /* length of the incoming header */
+{
+ struct Curl_header_store *hs;
+ struct Curl_header_store *newhs;
+ size_t olen; /* length of the old value */
+ size_t oalloc; /* length of the old name + value + separator */
+ size_t offset;
+ DEBUGASSERT(data->state.prevhead);
+ hs = data->state.prevhead;
+ olen = strlen(hs->value);
+ offset = hs->value - hs->buffer;
+ oalloc = olen + offset + 1;
+
+ /* skip all trailing space letters */
+ while(vlen && ISSPACE(value[vlen - 1]))
+ vlen--;
+
+ /* save only one leading space */
+ while((vlen > 1) && ISBLANK(value[0]) && ISBLANK(value[1])) {
+ vlen--;
+ value++;
+ }
+
+ /* since this header block might move in the realloc below, it needs to
+ first be unlinked from the list and then re-added again after the
+ realloc */
+ Curl_llist_remove(&data->state.httphdrs, &hs->node, NULL);
+
+ /* new size = struct + new value length + old name+value length */
+ newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1);
+ if(!newhs)
+ return CURLE_OUT_OF_MEMORY;
+ /* ->name' and ->value point into ->buffer (to keep the header allocation
+ in a single memory block), which now potentially have moved. Adjust
+ them. */
+ newhs->name = newhs->buffer;
+ newhs->value = &newhs->buffer[offset];
+
+ /* put the data at the end of the previous data, not the newline */
+ memcpy(&newhs->value[olen], value, vlen);
+ newhs->value[olen + vlen] = 0; /* null-terminate at newline */
+
+ /* insert this node into the list of headers */
+ Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
+ newhs, &newhs->node);
+ data->state.prevhead = newhs;
+ return CURLE_OK;
+}
+
+
/*
* Curl_headers_push() gets passed a full HTTP header to store. It gets called
* immediately before the header callback. The header is CRLF terminated.
@@ -242,6 +295,15 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
}
hlen = end - header + 1;
+ if((header[0] == ' ') || (header[0] == '\t')) {
+ if(data->state.prevhead)
+ /* line folding, append value to the previous header's value */
+ return unfold_value(data, header, hlen);
+ else
+ /* can't unfold without a previous header */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
hs = calloc(1, sizeof(*hs) + hlen);
if(!hs)
return CURLE_OUT_OF_MEMORY;
@@ -260,7 +322,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
/* insert this node into the list of headers */
Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
hs, &hs->node);
-
+ data->state.prevhead = hs;
return CURLE_OK;
fail:
free(hs);
diff --git a/Utilities/cmcurl/lib/headers.h b/Utilities/cmcurl/lib/headers.h
index 48c013b04..96332dbd0 100644
--- a/Utilities/cmcurl/lib/headers.h
+++ b/Utilities/cmcurl/lib/headers.h
@@ -20,10 +20,12 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HEADERS_API)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
struct Curl_header_store {
struct Curl_llist_element node;
diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index 85b175d45..dfb0db575 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/lib/hmac.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2104 Keyed-Hashing for Message Authentication
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/hostasyn.c b/Utilities/cmcurl/lib/hostasyn.c
index f7d99ce9a..0bfbe2ef8 100644
--- a/Utilities/cmcurl/lib/hostasyn.c
+++ b/Utilities/cmcurl/lib/hostasyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 7000b8550..941ecacf4 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -179,7 +181,7 @@ create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
len = buflen - 7;
/* store and lower case the name */
while(len--)
- *ptr++ = (char)TOLOWER(*name++);
+ *ptr++ = Curl_raw_tolower(*name++);
msnprintf(ptr, 7, ":%u", port);
}
@@ -295,6 +297,31 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
}
}
+ /* See if the returned entry matches the required resolve mode */
+ if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
+ int pf = PF_INET;
+ bool found = false;
+ struct Curl_addrinfo *addr = dns->addr;
+
+#ifdef PF_INET6
+ if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+#endif
+
+ while(addr) {
+ if(addr->ai_family == pf) {
+ found = true;
+ break;
+ }
+ addr = addr->ai_next;
+ }
+
+ if(!found) {
+ infof(data, "Hostname in DNS cache doesn't have needed family, zapped");
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ }
+ }
return dns;
}
@@ -461,12 +488,12 @@ Curl_cache_addr(struct Curl_easy *data,
}
#ifdef ENABLE_IPV6
-/* return a static IPv6 resolve for 'localhost' */
-static struct Curl_addrinfo *get_localhost6(int port)
+/* return a static IPv6 ::1 for the name */
+static struct Curl_addrinfo *get_localhost6(int port, const char *name)
{
struct Curl_addrinfo *ca;
const size_t ss_size = sizeof(struct sockaddr_in6);
- const size_t hostlen = strlen("localhost");
+ const size_t hostlen = strlen(name);
struct sockaddr_in6 sa6;
unsigned char ipv6[16];
unsigned short port16 = (unsigned short)(port & 0xffff);
@@ -491,19 +518,19 @@ static struct Curl_addrinfo *get_localhost6(int port)
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, &sa6, ss_size);
ca->ai_canonname = (char *)ca->ai_addr + ss_size;
- strcpy(ca->ai_canonname, "localhost");
+ strcpy(ca->ai_canonname, name);
return ca;
}
#else
-#define get_localhost6(x) NULL
+#define get_localhost6(x,y) NULL
#endif
-/* return a static IPv4 resolve for 'localhost' */
-static struct Curl_addrinfo *get_localhost(int port)
+/* return a static IPv4 127.0.0.1 for the given name */
+static struct Curl_addrinfo *get_localhost(int port, const char *name)
{
struct Curl_addrinfo *ca;
const size_t ss_size = sizeof(struct sockaddr_in);
- const size_t hostlen = strlen("localhost");
+ const size_t hostlen = strlen(name);
struct sockaddr_in sa;
unsigned int ipv4;
unsigned short port16 = (unsigned short)(port & 0xffff);
@@ -527,8 +554,8 @@ static struct Curl_addrinfo *get_localhost(int port)
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, &sa, ss_size);
ca->ai_canonname = (char *)ca->ai_addr + ss_size;
- strcpy(ca->ai_canonname, "localhost");
- ca->ai_next = get_localhost6(port);
+ strcpy(ca->ai_canonname, name);
+ ca->ai_next = get_localhost6(port, name);
return ca;
}
@@ -544,7 +571,11 @@ bool Curl_ipv6works(struct Curl_easy *data)
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
- return data->multi->ipv6_works;
+ if(data->multi->ipv6_up == IPV6_UNKNOWN) {
+ bool works = Curl_ipv6works(NULL);
+ data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD;
+ }
+ return data->multi->ipv6_up == IPV6_WORKS;
}
else {
int ipv6_works = -1;
@@ -581,6 +612,17 @@ bool Curl_host_is_ipnum(const char *hostname)
return FALSE;
}
+
+/* return TRUE if 'part' is a case insensitive tail of 'full' */
+static bool tailmatch(const char *full, const char *part)
+{
+ size_t plen = strlen(part);
+ size_t flen = strlen(full);
+ if(plen > flen)
+ return FALSE;
+ return strncasecompare(part, &full[flen - plen], plen);
+}
+
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
@@ -716,8 +758,9 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
return CURLRESOLV_ERROR;
- if(strcasecompare(hostname, "localhost"))
- addr = get_localhost(port);
+ if(strcasecompare(hostname, "localhost") ||
+ tailmatch(hostname, ".localhost"))
+ addr = get_localhost(port, hostname);
#ifndef CURL_DISABLE_DOH
else if(allowDOH && data->set.doh && !ipnum)
addr = Curl_doh(data, hostname, port, &respwait);
@@ -991,9 +1034,9 @@ static void freednsentry(void *freethis)
/*
* Curl_init_dnscache() inits a new DNS cache.
*/
-void Curl_init_dnscache(struct Curl_hash *hash)
+void Curl_init_dnscache(struct Curl_hash *hash, int size)
{
- Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare,
+ Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
freednsentry);
}
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 1db598184..9d3170737 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -130,7 +132,7 @@ void Curl_resolv_unlock(struct Curl_easy *data,
struct Curl_dns_entry *dns);
/* init a new dns cache */
-void Curl_init_dnscache(struct Curl_hash *hash);
+void Curl_init_dnscache(struct Curl_hash *hash, int hashsize);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct Curl_easy *data);
diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index 1fd791015..1dd54e879 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/lib/hostip4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -110,7 +112,8 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV4 */
-#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES)
+#if defined(CURLRES_IPV4) && \
+ !defined(CURLRES_ARES) && !defined(CURLRES_AMIGA)
/*
* Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
@@ -295,4 +298,5 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
return ai;
}
-#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */
+#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) &&
+ !defined(CURLRES_AMIGA) */
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index c2d5f08e3..c62c254c7 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -94,8 +96,8 @@ static void dump_addrinfo(struct connectdata *conn,
* non-ares version).
*
* Returns name information about the given hostname and port number. If
- * successful, the 'addrinfo' is returned and the forth argument will point to
- * memory we need to free after use. That memory *MUST* be freed with
+ * successful, the 'addrinfo' is returned and the fourth argument will point
+ * to memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
@@ -115,7 +117,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* synchronous response only */
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
diff --git a/Utilities/cmcurl/lib/hostsyn.c b/Utilities/cmcurl/lib/hostsyn.c
index c00c2744c..ee54363bf 100644
--- a/Utilities/cmcurl/lib/hostsyn.c
+++ b/Utilities/cmcurl/lib/hostsyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
index b9fa6f7af..e3b686ebf 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
* The Strict-Transport-Security header is defined in RFC 6797:
@@ -35,7 +37,7 @@
#include "sendf.h"
#include "strtoofft.h"
#include "parsedate.h"
-#include "rand.h"
+#include "fopen.h"
#include "rename.h"
#include "strtoofft.h"
@@ -154,7 +156,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_OK;
do {
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(Curl_strncasecompare("max-age=", p, 8)) {
bool quoted = FALSE;
@@ -165,7 +167,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_BAD_FUNCTION_ARGUMENT;
p += 8;
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == '\"') {
p++;
@@ -198,7 +200,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
p++;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == ';')
p++;
@@ -354,8 +356,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
- char *tempstore;
- unsigned char randsuffix[9];
+ char *tempstore = NULL;
if(!h)
/* no cache activated */
@@ -369,17 +370,8 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
/* marked as read-only, no file or zero length file name */
goto skipsave;
- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
- return CURLE_FAILED_INIT;
-
- tempstore = aprintf("%s.%s.tmp", file, randsuffix);
- if(!tempstore)
- return CURLE_OUT_OF_MEMORY;
-
- out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
- result = CURLE_WRITE_ERROR;
- else {
+ result = Curl_fopen(data, file, &out, &tempstore);
+ if(!result) {
fputs("# Your HSTS cache. https://curl.se/docs/hsts.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
@@ -391,10 +383,10 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
break;
}
fclose(out);
- if(!result && Curl_rename(tempstore, file))
+ if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
- if(result)
+ if(result && tempstore)
unlink(tempstore);
}
free(tempstore);
@@ -494,8 +486,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
/*
* Load the HSTS cache from the given file. The text based line-oriented file
- * format is documented here:
- * https://github.com/curl/curl/wiki/HSTS
+ * format is documented here: https://curl.se/docs/hsts.html
*
* This function only returns error on major problems that prevent hsts
* handling to work completely. It will ignore individual syntactical errors
diff --git a/Utilities/cmcurl/lib/hsts.h b/Utilities/cmcurl/lib/hsts.h
index 653c05348..0e36a7756 100644
--- a/Utilities/cmcurl/lib/hsts.h
+++ b/Utilities/cmcurl/lib/hsts.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index b215307dc..f57859e8b 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -82,6 +84,7 @@
#include "strdup.h"
#include "altsvc.h"
#include "hsts.h"
+#include "ws.h"
#include "c-hyper.h"
/* The last 3 #include files should be in this order */
@@ -112,6 +115,10 @@ static int https_getsock(struct Curl_easy *data,
#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+#endif
/*
* HTTP handler interface.
@@ -140,6 +147,32 @@ const struct Curl_handler Curl_handler_http = {
PROTOPT_USERPWDCTRL
};
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_ws = {
+ "WS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTP, /* defport */
+ CURLPROTO_WS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+#endif
+
#ifdef USE_SSL
/*
* HTTPS handler interface.
@@ -164,11 +197,38 @@ const struct Curl_handler Curl_handler_https = {
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_wss = {
+ "WSS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ https_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ https_getsock, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_WSS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
PROTOPT_USERPWDCTRL
};
#endif
+#endif
+
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -203,6 +263,16 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
return CURLE_OK;
}
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* websockets is 1.1 only (for now) */
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
+ return http_setup_conn(data, conn);
+}
+#endif
+
#ifndef CURL_DISABLE_PROXY
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
@@ -651,21 +721,6 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
return result;
}
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- return (!data->state.this_is_a_follow ||
- data->set.allow_auth_to_other_hosts ||
- (data->state.first_host &&
- strcasecompare(data->state.first_host, conn->host.name) &&
- (data->state.first_remote_port == conn->remote_port) &&
- (data->state.first_remote_protocol == conn->handler->protocol)));
-}
-
#ifndef CURL_DISABLE_HTTP_AUTH
/*
* Output the correct authentication header depending on the auth type
@@ -864,7 +919,7 @@ Curl_http_output_auth(struct Curl_easy *data,
/* To prevent the user+password to get sent to other than the original host
due to a location-follow */
- if(Curl_allow_auth_to_host(data)
+ if(Curl_auth_allowed_to_host(data)
#ifndef CURL_DISABLE_NETRC
|| conn->bits.netrc
#endif
@@ -1516,7 +1571,7 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
}
#endif
- if(conn->given->protocol & CURLPROTO_HTTPS) {
+ if(conn->given->flags & PROTOPT_SSL) {
/* perform SSL initialization */
result = https_connecting(data, done);
if(result)
@@ -1641,6 +1696,7 @@ CURLcode Curl_http_done(struct Curl_easy *data,
Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
Curl_hyper_done(data);
+ Curl_ws_done(data);
if(status)
return status;
@@ -1917,7 +1973,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to
other hosts */
- !Curl_allow_auth_to_host(data))
+ !Curl_auth_allowed_to_host(data))
;
else {
#ifdef USE_HYPER
@@ -2030,7 +2086,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
const char **method, Curl_HttpReq *reqp)
{
- Curl_HttpReq httpreq = data->state.httpreq;
+ Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq;
const char *request;
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
data->set.upload)
@@ -2149,9 +2205,9 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
[brackets] if the host name is a plain IPv6-address. RFC2732-style. */
const char *host = conn->host.name;
- if(((conn->given->protocol&CURLPROTO_HTTPS) &&
+ if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) &&
(conn->remote_port == PORT_HTTPS)) ||
- ((conn->given->protocol&CURLPROTO_HTTP) &&
+ ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) &&
(conn->remote_port == PORT_HTTP)) )
/* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
the port number in the host string */
@@ -2700,6 +2756,13 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP request");
+#ifdef USE_WEBSOCKETS
+ else if((conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
+ !(data->set.connect_only))
+ /* Set up the transfer for two-way since without CONNECT_ONLY set, this
+ request probably wants to send data too post upgrade */
+ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
+#endif
else
/* HTTP GET/HEAD download: */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
@@ -2709,12 +2772,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
#if !defined(CURL_DISABLE_COOKIES)
+
CURLcode Curl_http_cookies(struct Curl_easy *data,
struct connectdata *conn,
struct dynbuf *r)
{
CURLcode result = CURLE_OK;
char *addcookies = NULL;
+ bool linecap = FALSE;
if(data->set.str[STRING_COOKIE] &&
!Curl_checkheaders(data, STRCONST("Cookie")))
addcookies = data->set.str[STRING_COOKIE];
@@ -2727,12 +2792,12 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
const char *host = data->state.aptr.cookiehost ?
data->state.aptr.cookiehost : conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
+ co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
secure_context);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
@@ -2746,6 +2811,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
if(result)
break;
}
+ if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >=
+ MAX_COOKIE_HEADER_LEN) {
+ infof(data, "Restricted outgoing cookies due to header size, "
+ "'%s' not sent", co->name);
+ linecap = TRUE;
+ break;
+ }
result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
co->name, co->value);
if(result)
@@ -2756,7 +2828,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
}
Curl_cookie_freelist(store);
}
- if(addcookies && !result) {
+ if(addcookies && !result && !linecap) {
if(!count)
result = Curl_dyn_addn(r, STRCONST("Cookie: "));
if(!result) {
@@ -3033,7 +3105,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(conn->transport != TRNSPRT_QUIC) {
if(conn->httpversion < 20) { /* unless the connection is re-used and
already http2 */
- switch(conn->negnpn) {
+ switch(conn->alpn) {
case CURL_HTTP_VERSION_2:
conn->httpversion = 20; /* we know we're on HTTP/2 now */
@@ -3245,6 +3317,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
result = Curl_http_cookies(data, conn, &req);
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, &req);
if(!result)
result = Curl_add_timecondition(data, &req);
if(!result)
@@ -3509,15 +3583,15 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
else if(checkprefix("Retry-After:", headp)) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
- if(-1 == date) {
- /* not a date, try it as a decimal number */
- (void)curlx_strtoofft(headp + strlen("Retry-After:"),
- NULL, 10, &retry_after);
+ /* Try it as a decimal number, if it works it is not a date */
+ (void)curlx_strtoofft(headp + strlen("Retry-After:"),
+ NULL, 10, &retry_after);
+ if(!retry_after) {
+ time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
+ if(-1 != date)
+ /* convert date to number of seconds into the future */
+ retry_after = date - time(NULL);
}
- else
- /* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
data->info.retry_after = retry_after; /* store it */
}
else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
@@ -3529,7 +3603,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
The second format was added since Sun's webserver
JavaWebServer/1.1.1 obviously sends the header this way!
The third added since some servers use that!
- The forth means the requested range was unsatisfied.
+ The fourth means the requested range was unsatisfied.
*/
char *ptr = headp + strlen("Content-Range:");
@@ -3557,7 +3631,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
const char *host = data->state.aptr.cookiehost?
data->state.aptr.cookiehost:conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
@@ -3641,7 +3715,14 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
#ifndef CURL_DISABLE_HSTS
/* If enabled, the header is incoming and this is over HTTPS */
else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
- (conn->handler->flags & PROTOPT_SSL)) {
+ ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+ /* allow debug builds to circumvent the HTTPS restriction */
+ getenv("CURL_HSTS_HTTP")
+#else
+ 0
+#endif
+ )) {
CURLcode check =
Curl_hsts_parse(data->hsts, data->state.up.hostname,
headp + strlen("Strict-Transport-Security:"));
@@ -3723,7 +3804,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
connclose(conn, "HTTP/1.0 close after body");
}
else if(conn->httpversion == 20 ||
- (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
/* HTTP/2 cannot avoid multiplexing since it is a core functionality
of the protocol */
@@ -3799,11 +3880,16 @@ static CURLcode verify_header(struct Curl_easy *data)
if(k->headerline < 2)
/* the first "header" is the status-line and it has no colon */
return CURLE_OK;
- ptr = memchr(header, ':', hlen);
- if(!ptr) {
- /* this is bad, bail out */
- failf(data, "Header without colon");
- return CURLE_WEIRD_SERVER_REPLY;
+ if(((header[0] == ' ') || (header[0] == '\t')) && k->headerline > 2)
+ /* line folding, can't happen on line 2 */
+ ;
+ else {
+ ptr = memchr(header, ':', hlen);
+ if(!ptr) {
+ /* this is bad, bail out */
+ failf(data, "Header without colon");
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
}
return CURLE_OK;
}
@@ -3944,9 +4030,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
break;
case 101:
/* Switching Protocols */
- if(k->upgr101 == UPGR101_REQUESTED) {
+ if(k->upgr101 == UPGR101_H2) {
/* Switching to HTTP/2 */
- infof(data, "Received 101");
+ infof(data, "Received 101, Switching to HTTP/2");
k->upgr101 = UPGR101_RECEIVED;
/* we'll get more headers (HTTP/2 response) */
@@ -3960,8 +4046,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return result;
*nread = 0;
}
+#ifdef USE_WEBSOCKETS
+ else if(k->upgr101 == UPGR101_WS) {
+ /* verify the response */
+ result = Curl_ws_accept(data);
+ if(result)
+ return result;
+ k->header = FALSE; /* no more header to parse! */
+ if(data->set.connect_only) {
+ k->keepon &= ~KEEP_RECV; /* read no more content */
+ *nread = 0;
+ }
+ }
+#endif
else {
- /* Switching to another protocol (e.g. WebSocket) */
+ /* Not switching to another protocol */
k->header = FALSE; /* no more header to parse! */
}
break;
@@ -4054,6 +4153,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return CURLE_HTTP_RETURNED_ERROR;
}
+#ifdef USE_WEBSOCKETS
+ /* All non-101 HTTP status codes are bad when wanting to upgrade to
+ websockets */
+ if(data->req.upgr101 == UPGR101_WS) {
+ failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+#endif
+
+
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index c4ab3c22d..f7cbb3424 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -20,8 +20,11 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
+#include "ws.h"
typedef enum {
HTTPREQ_GET,
@@ -48,6 +51,15 @@ extern const struct Curl_handler Curl_handler_http;
extern const struct Curl_handler Curl_handler_https;
#endif
+#ifdef USE_WEBSOCKETS
+extern const struct Curl_handler Curl_handler_ws;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_wss;
+#endif
+#endif /* websockets */
+
+
/* Header specific functions */
bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
@@ -216,6 +228,10 @@ struct HTTP {
HTTPSEND_BODY /* sending body */
} sending;
+#ifdef USE_WEBSOCKETS
+ struct websocket ws;
+#endif
+
#ifndef CURL_DISABLE_HTTP
struct dynbuf send_buffer; /* used if the request couldn't be sent in one
chunk, points to an allocated send_buffer
@@ -225,13 +241,11 @@ struct HTTP {
/*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */
- bool bodystarted;
/* We store non-final and final response headers here, per-stream */
struct dynbuf header_recvbuf;
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
upper layer */
struct dynbuf trailer_recvbuf;
- int status_code; /* HTTP status code */
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
@@ -242,6 +256,8 @@ struct HTTP {
uint32_t error; /* HTTP/2 stream error code */
#endif
#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
+ bool bodystarted;
+ int status_code; /* HTTP status code */
bool closed; /* TRUE on HTTP2 stream close */
char *mem; /* points to a buffer in memory to store received data */
size_t len; /* size of the buffer 'mem' points to */
@@ -258,6 +274,7 @@ struct HTTP {
#ifndef USE_MSH3
/*********** for HTTP/3 we store stream-local data here *************/
int64_t stream3_id; /* stream we are interested in */
+ uint64_t error3; /* HTTP/3 stream error code */
bool firstheader; /* FALSE until headers arrive */
bool firstbody; /* FALSE until body arrives */
bool h3req; /* FALSE until request is issued */
@@ -364,10 +381,4 @@ Curl_http_output_auth(struct Curl_easy *data,
bool proxytunnel); /* TRUE if this is the request setting
up the proxy tunnel */
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data);
-
#endif /* HEADER_CURL_HTTP_H */
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index 0120b8631..b7409b027 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -643,7 +645,7 @@ static int push_promise(struct Curl_easy *data,
frame->promised_stream_id,
newhandle);
if(rv) {
- infof(data, "failed to set user_data for stream %d",
+ infof(data, "failed to set user_data for stream %u",
frame->promised_stream_id);
DEBUGASSERT(0);
rv = CURL_PUSH_DENY;
@@ -713,19 +715,19 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
if(!data_s) {
H2BUGF(infof(data,
- "No Curl_easy associated with stream: %x",
+ "No Curl_easy associated with stream: %u",
stream_id));
return 0;
}
stream = data_s->req.p.http;
if(!stream) {
- H2BUGF(infof(data_s, "No proto pointer for stream: %x",
+ H2BUGF(infof(data_s, "No proto pointer for stream: %u",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x",
+ H2BUGF(infof(data_s, "on_frame_recv() header %x stream %u",
frame->hd.type, stream_id));
switch(frame->hd.type) {
@@ -913,7 +915,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
/* remove the entry from the hash as the stream is now gone */
rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
if(rv) {
- infof(data_s, "http/2: failed to clear user_data for stream %d",
+ infof(data_s, "http/2: failed to clear user_data for stream %u",
stream_id);
DEBUGASSERT(0);
}
@@ -1050,6 +1052,12 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
else if(stream->push_headers_used ==
stream->push_headers_alloc) {
char **headp;
+ if(stream->push_headers_alloc > 1000) {
+ /* this is beyond crazy many headers, bail out */
+ failf(data_s, "Too many PUSH_PROMISE headers");
+ Curl_safefree(stream->push_headers);
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
stream->push_headers_alloc *= 2;
headp = Curl_saferealloc(stream->push_headers,
stream->push_headers_alloc * sizeof(char *));
@@ -1240,13 +1248,13 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
/* do this before the reset handling, as that might clear ->stream_id */
if(http->stream_id == httpc->pause_stream_id) {
- H2BUGF(infof(data, "DONE the pause stream (%x)", http->stream_id));
+ H2BUGF(infof(data, "DONE the pause stream (%u)", http->stream_id));
httpc->pause_stream_id = 0;
}
if(premature || (!http->closed && http->stream_id)) {
/* RST_STREAM */
set_transfer(httpc, data); /* set the transfer */
- H2BUGF(infof(data, "RST stream %x", http->stream_id));
+ H2BUGF(infof(data, "RST stream %u", http->stream_id));
if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
http->stream_id, NGHTTP2_STREAM_CLOSED))
(void)nghttp2_session_send(httpc->h2);
@@ -1260,7 +1268,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
int rv = nghttp2_session_set_stream_user_data(httpc->h2,
http->stream_id, 0);
if(rv) {
- infof(data, "http/2: failed to clear user_data for stream %d",
+ infof(data, "http/2: failed to clear user_data for stream %u",
http->stream_id);
DEBUGASSERT(0);
}
@@ -1269,6 +1277,27 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
}
}
+static int client_new(struct connectdata *conn,
+ nghttp2_session_callbacks *callbacks)
+{
+#if NGHTTP2_VERSION_NUM < 0x013200
+ /* before 1.50.0 */
+ return nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
+#else
+ nghttp2_option *o;
+ int rc = nghttp2_option_new(&o);
+ if(rc)
+ return rc;
+ /* turn off RFC 9113 leading and trailing white spaces validation against
+ HTTP field value. */
+ nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
+ rc = nghttp2_session_client_new2(&conn->proto.httpc.h2, callbacks, conn,
+ o);
+ nghttp2_option_del(o);
+ return rc;
+#endif
+}
+
/*
* Initialize nghttp2 for a Curl connection
*/
@@ -1309,7 +1338,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
/* The nghttp2 session is not yet setup, do it */
- rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
+ rc = client_new(conn, callbacks);
nghttp2_session_callbacks_del(callbacks);
@@ -1363,7 +1392,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
- k->upgr101 = UPGR101_REQUESTED;
+ k->upgr101 = UPGR101_H2;
return result;
}
@@ -1519,7 +1548,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
if(stream->error == NGHTTP2_REFUSED_STREAM) {
- H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection",
+ H2BUGF(infof(data, "REFUSED_STREAM (%u), try again on a new connection",
stream->stream_id));
connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
data->state.refused_stream = TRUE;
@@ -1527,7 +1556,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
return -1;
}
else if(stream->error != NGHTTP2_NO_ERROR) {
- failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
+ failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
stream->stream_id, nghttp2_http2_strerror(stream->error),
stream->error);
*err = CURLE_HTTP2_STREAM;
@@ -1535,7 +1564,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
}
if(!stream->bodystarted) {
- failf(data, "HTTP/2 stream %d was closed cleanly, but before getting "
+ failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
" all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
@@ -1740,7 +1769,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
if(stream->closed)
/* closed overrides paused */
return 0;
- H2BUGF(infof(data, "stream %x is paused, pause id: %x",
+ H2BUGF(infof(data, "stream %u is paused, pause id: %u",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
@@ -1771,7 +1800,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
/* This will happen when the server or proxy server is SIGKILLed
during data transfer. We should emit an error since our data
received may be incomplete. */
- failf(data, "HTTP/2 stream %d was not closed cleanly before"
+ failf(data, "HTTP/2 stream %u was not closed cleanly before"
" end of the underlying stream",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
@@ -1855,7 +1884,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
if(stream->stream_id != -1) {
if(stream->close_handled) {
- infof(data, "stream %d closed", stream->stream_id);
+ infof(data, "stream %u closed", stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
@@ -1968,13 +1997,13 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
if(stream_id < 0) {
H2BUGF(infof(data,
- "http2_send() nghttp2_submit_request error (%s)%d",
+ "http2_send() nghttp2_submit_request error (%s)%u",
nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
return -1;
}
- infof(data, "Using Stream ID: %x (easy handle %p)",
+ infof(data, "Using Stream ID: %u (easy handle %p)",
stream_id, (void *)data);
stream->stream_id = stream_id;
@@ -2094,7 +2123,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
stream->stream_id,
data);
if(rv) {
- infof(data, "http/2: failed to set user_data for stream %d",
+ infof(data, "http/2: failed to set user_data for stream %u",
stream->stream_id);
DEBUGASSERT(0);
}
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index d6986d97f..f0390596c 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.c b/Utilities/cmcurl/lib/http_aws_sigv4.c
index 210c3dbe5..440eb385f 100644
--- a/Utilities/cmcurl/lib/http_aws_sigv4.c
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -27,8 +29,6 @@
#include "urldata.h"
#include "strcase.h"
#include "strdup.h"
-#include "vauth/vauth.h"
-#include "vauth/digest.h"
#include "http_aws_sigv4.h"
#include "curl_sha256.h"
#include "transfer.h"
@@ -44,6 +44,8 @@
#include "curl_memory.h"
#include "memdebug.h"
+#include "slist.h"
+
#define HMAC_SHA256(k, kl, d, dl, o) \
do { \
ret = Curl_hmacit(Curl_HMAC_SHA256, \
@@ -51,19 +53,219 @@
(unsigned int)kl, \
(unsigned char *)d, \
(unsigned int)dl, o); \
- if(ret != CURLE_OK) { \
+ if(ret) { \
goto fail; \
} \
} while(0)
+#define TIMESTAMP_SIZE 17
+
static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
{
int i;
DEBUGASSERT(dst_l >= 65);
for(i = 0; i < 32; ++i) {
- curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ }
+}
+
+static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
+{
+ char *tmp = Curl_checkheaders(data, sig_hdr, strlen(sig_hdr));
+
+ if(tmp)
+ return tmp;
+ return Curl_checkheaders(data, STRCONST("Date"));
+}
+
+/* remove whitespace, and lowercase all headers */
+static void trim_headers(struct curl_slist *head)
+{
+ struct curl_slist *l;
+ for(l = head; l; l = l->next) {
+ char *value; /* to read from */
+ char *store;
+ size_t colon = strcspn(l->data, ":");
+ Curl_strntolower(l->data, l->data, colon);
+
+ value = &l->data[colon];
+ if(!*value)
+ continue;
+ ++value;
+ store = value;
+
+ /* skip leading whitespace */
+ while(*value && ISBLANK(*value))
+ value++;
+
+ while(*value) {
+ int space = 0;
+ while(*value && ISBLANK(*value)) {
+ value++;
+ space++;
+ }
+ if(space) {
+ /* replace any number of consecutive whitespace with a single space,
+ unless at the end of the string, then nothing */
+ if(*value)
+ *store++ = ' ';
+ }
+ else
+ *store++ = *value++;
+ }
+ *store = 0; /* null terminate */
+ }
+}
+
+/* maximum lenth for the aws sivg4 parts */
+#define MAX_SIGV4_LEN 64
+#define MAX_SIGV4_LEN_TXT "64"
+
+#define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date"))
+
+#define MAX_HOST_LEN 255
+/* FQDN + host: */
+#define FULL_HOST_LEN (MAX_HOST_LEN + sizeof("host:"))
+
+/* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
+#define DATE_FULL_HDR_LEN (DATE_HDR_KEY_LEN + TIMESTAMP_SIZE + 1)
+
+/* timestamp should point to a buffer of at last TIMESTAMP_SIZE bytes */
+static CURLcode make_headers(struct Curl_easy *data,
+ const char *hostname,
+ char *timestamp,
+ char *provider1,
+ char **date_header,
+ struct dynbuf *canonical_headers,
+ struct dynbuf *signed_headers)
+{
+ char date_hdr_key[DATE_HDR_KEY_LEN];
+ char date_full_hdr[DATE_FULL_HDR_LEN];
+ struct curl_slist *head = NULL;
+ struct curl_slist *tmp_head = NULL;
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct curl_slist *l;
+ int again = 1;
+
+ /* provider1 mid */
+ Curl_strntolower(provider1, provider1, strlen(provider1));
+ provider1[0] = Curl_raw_toupper(provider1[0]);
+
+ msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%s-Date", provider1);
+
+ /* provider1 lowercase */
+ Curl_strntolower(provider1, provider1, 1); /* first byte only */
+ msnprintf(date_full_hdr, DATE_FULL_HDR_LEN,
+ "x-%s-date:%s", provider1, timestamp);
+
+ if(Curl_checkheaders(data, STRCONST("Host"))) {
+ head = NULL;
+ }
+ else {
+ char full_host[FULL_HOST_LEN + 1];
+
+ if(data->state.aptr.host) {
+ size_t pos;
+
+ if(strlen(data->state.aptr.host) > FULL_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ strcpy(full_host, data->state.aptr.host);
+ /* remove /r/n as the separator for canonical request must be '\n' */
+ pos = strcspn(full_host, "\n\r");
+ full_host[pos] = 0;
+ }
+ else {
+ if(strlen(hostname) > MAX_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ msnprintf(full_host, FULL_HOST_LEN, "host:%s", hostname);
+ }
+
+ head = curl_slist_append(NULL, full_host);
+ if(!head)
+ goto fail;
+ }
+
+
+ for(l = data->set.headers; l; l = l->next) {
+ tmp_head = curl_slist_append(head, l->data);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ }
+
+ trim_headers(head);
+
+ *date_header = find_date_hdr(data, date_hdr_key);
+ if(!*date_header) {
+ tmp_head = curl_slist_append(head, date_full_hdr);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ *date_header = curl_maprintf("%s: %s", date_hdr_key, timestamp);
+ }
+ else {
+ char *value;
+
+ *date_header = strdup(*date_header);
+ if(!*date_header)
+ goto fail;
+
+ value = strchr(*date_header, ':');
+ if(!value)
+ goto fail;
+ ++value;
+ while(ISBLANK(*value))
+ ++value;
+ strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
+ timestamp[TIMESTAMP_SIZE - 1] = 0;
+ }
+
+ /* alpha-sort in a case sensitive manner */
+ do {
+ again = 0;
+ for(l = head; l; l = l->next) {
+ struct curl_slist *next = l->next;
+
+ if(next && strcmp(l->data, next->data) > 0) {
+ char *tmp = l->data;
+
+ l->data = next->data;
+ next->data = tmp;
+ again = 1;
+ }
+ }
+ } while(again);
+
+ for(l = head; l; l = l->next) {
+ char *tmp;
+
+ if(Curl_dyn_add(canonical_headers, l->data))
+ goto fail;
+ if(Curl_dyn_add(canonical_headers, "\n"))
+ goto fail;
+
+ tmp = strchr(l->data, ':');
+ if(tmp)
+ *tmp = 0;
+
+ if(l != head) {
+ if(Curl_dyn_add(signed_headers, ";"))
+ goto fail;
+ }
+ if(Curl_dyn_add(signed_headers, l->data))
+ goto fail;
}
+
+ ret = CURLE_OK;
+fail:
+ curl_slist_free_all(head);
+
+ return ret;
}
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
@@ -71,29 +273,21 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
CURLcode ret = CURLE_OUT_OF_MEMORY;
struct connectdata *conn = data->conn;
size_t len;
- const char *tmp0;
- const char *tmp1;
- char *provider0_low = NULL;
- char *provider0_up = NULL;
- char *provider1_low = NULL;
- char *provider1_mid = NULL;
- char *region = NULL;
- char *service = NULL;
+ const char *arg;
+ char provider0[MAX_SIGV4_LEN + 1]="";
+ char provider1[MAX_SIGV4_LEN + 1]="";
+ char region[MAX_SIGV4_LEN + 1]="";
+ char service[MAX_SIGV4_LEN + 1]="";
const char *hostname = conn->host.name;
-#ifdef DEBUGBUILD
- char *force_timestamp;
-#endif
time_t clock;
struct tm tm;
- char timestamp[17];
+ char timestamp[TIMESTAMP_SIZE];
char date[9];
- const char *content_type = Curl_checkheaders(data, STRCONST("Content-Type"));
- char *canonical_headers = NULL;
- char *signed_headers = NULL;
- Curl_HttpReq httpreq;
- const char *method;
- size_t post_data_len;
- const char *post_data = data->set.postfields ? data->set.postfields : "";
+ struct dynbuf canonical_headers;
+ struct dynbuf signed_headers;
+ char *date_header = NULL;
+ const char *post_data = data->set.postfields;
+ size_t post_data_len = 0;
unsigned char sha_hash[32];
char sha_hex[65];
char *canonical_request = NULL;
@@ -101,10 +295,9 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
char *credential_scope = NULL;
char *str_to_sign = NULL;
const char *user = data->state.aptr.user ? data->state.aptr.user : "";
- const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
char *secret = NULL;
- unsigned char tmp_sign0[32] = {0};
- unsigned char tmp_sign1[32] = {0};
+ unsigned char sign0[32] = {0};
+ unsigned char sign1[32] = {0};
char *auth_headers = NULL;
DEBUGASSERT(!proxy);
@@ -115,6 +308,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
return CURLE_OK;
}
+ /* we init thoses buffers here, so goto fail will free initialized dynbuf */
+ Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
+ Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
+
/*
* Parameters parsing
* Google and Outscale use the same OSC or GOOG,
@@ -122,223 +319,154 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
* AWS is the default because most of non-amazon providers
* are still using aws:amz as a prefix.
*/
- tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ arg = data->set.str[STRING_AWS_SIGV4] ?
data->set.str[STRING_AWS_SIGV4] : "aws:amz";
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "first provider can't be empty");
+
+ /* provider1[:provider2[:region[:service]]]
+
+ No string can be longer than N bytes of non-whitespace
+ */
+ (void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "s",
+ provider0, provider1, region, service);
+ if(!provider0[0]) {
+ failf(data, "first provider can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
- provider0_low = malloc(len + 1);
- provider0_up = malloc(len + 1);
- if(!provider0_low || !provider0_up) {
- goto fail;
- }
- Curl_strntolower(provider0_low, tmp0, len);
- provider0_low[len] = '\0';
- Curl_strntoupper(provider0_up, tmp0, len);
- provider0_up[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "second provider can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- provider1_low = malloc(len + 1);
- provider1_mid = malloc(len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- Curl_strntolower(provider1_low, tmp0, len);
- provider1_low[len] = '\0';
- Curl_strntolower(provider1_mid, tmp0, len);
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- provider1_mid[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "region can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
- goto fail;
- }
- region[len] = '\0';
+ else if(!provider1[0])
+ strcpy(provider1, provider0);
- if(tmp1) {
- tmp0 = tmp1 + 1;
- service = strdup(tmp0);
- if(!service) {
- goto fail;
- }
- if(strlen(service) < 1) {
- infof(data, "service can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- }
- }
- }
- else {
- provider1_low = Curl_memdup(provider0_low, len + 1);
- provider1_mid = Curl_memdup(provider0_low, len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- }
-
- if(!service) {
- tmp0 = hostname;
- tmp1 = strchr(tmp0, '.');
- len = tmp1 - tmp0;
- if(!tmp1 || len < 1) {
- infof(data, "service missing in parameters or hostname");
+ if(!service[0]) {
+ char *hostdot = strchr(hostname, '.');
+ if(!hostdot) {
+ failf(data, "service missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- service = Curl_memdup(tmp0, len + 1);
- if(!service) {
+ len = hostdot - hostname;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "service too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(service, hostname, len);
service[len] = '\0';
- if(!region) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, '.');
- len = tmp1 - tmp0;
- if(!tmp1 || len < 1) {
- infof(data, "region missing in parameters or hostname");
+ if(!region[0]) {
+ const char *reg = hostdot + 1;
+ const char *hostreg = strchr(reg, '.');
+ if(!hostreg) {
+ failf(data, "region missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
+ len = hostreg - reg;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "region too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(region, reg, len);
region[len] = '\0';
}
}
#ifdef DEBUGBUILD
- force_timestamp = getenv("CURL_FORCETIME");
- if(force_timestamp)
- clock = 0;
- else
- time(&clock);
+ {
+ char *force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+ }
#else
time(&clock);
#endif
ret = Curl_gmtime(clock, &tm);
- if(ret != CURLE_OK) {
+ if(ret) {
goto fail;
}
if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ ret = CURLE_OUT_OF_MEMORY;
goto fail;
}
+
+ ret = make_headers(data, hostname, timestamp, provider1,
+ &date_header, &canonical_headers, &signed_headers);
+ if(ret)
+ goto fail;
+ ret = CURLE_OUT_OF_MEMORY;
+
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
- if(content_type) {
- content_type = strchr(content_type, ':');
- if(!content_type) {
- ret = CURLE_FAILED_INIT;
- goto fail;
- }
- content_type++;
- /* Skip whitespace now */
- while(*content_type == ' ' || *content_type == '\t')
- ++content_type;
-
- canonical_headers = curl_maprintf("content-type:%s\n"
- "host:%s\n"
- "x-%s-date:%s\n",
- content_type,
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("content-type;host;x-%s-date",
- provider1_low);
- }
- else {
- canonical_headers = curl_maprintf("host:%s\n"
- "x-%s-date:%s\n",
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
- }
-
- if(!canonical_headers || !signed_headers) {
- goto fail;
+ if(post_data) {
+ if(data->set.postfieldsize < 0)
+ post_data_len = strlen(post_data);
+ else
+ post_data_len = (size_t)data->set.postfieldsize;
}
-
- if(data->set.postfieldsize < 0)
- post_data_len = strlen(post_data);
- else
- post_data_len = (size_t)data->set.postfieldsize;
if(Curl_sha256it(sha_hash, (const unsigned char *) post_data,
- post_data_len)) {
+ post_data_len))
goto fail;
- }
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
- Curl_http_method(data, conn, &method, &httpreq);
-
- canonical_request =
- curl_maprintf("%s\n" /* HTTPRequestMethod */
- "%s\n" /* CanonicalURI */
- "%s\n" /* CanonicalQueryString */
- "%s\n" /* CanonicalHeaders */
- "%s\n" /* SignedHeaders */
- "%s", /* HashedRequestPayload in hex */
- method,
- data->state.up.path,
- data->state.up.query ? data->state.up.query : "",
- canonical_headers,
- signed_headers,
- sha_hex);
- if(!canonical_request) {
- goto fail;
+ {
+ Curl_HttpReq httpreq;
+ const char *method;
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ canonical_request =
+ curl_maprintf("%s\n" /* HTTPRequestMethod */
+ "%s\n" /* CanonicalURI */
+ "%s\n" /* CanonicalQueryString */
+ "%s\n" /* CanonicalHeaders */
+ "%s\n" /* SignedHeaders */
+ "%s", /* HashedRequestPayload in hex */
+ method,
+ data->state.up.path,
+ data->state.up.query ? data->state.up.query : "",
+ Curl_dyn_ptr(&canonical_headers),
+ Curl_dyn_ptr(&signed_headers),
+ sha_hex);
+ if(!canonical_request)
+ goto fail;
}
- request_type = curl_maprintf("%s4_request", provider0_low);
- if(!request_type) {
+ /* provider 0 lowercase */
+ Curl_strntolower(provider0, provider0, strlen(provider0));
+ request_type = curl_maprintf("%s4_request", provider0);
+ if(!request_type)
goto fail;
- }
credential_scope = curl_maprintf("%s/%s/%s/%s",
date, region, service, request_type);
- if(!credential_scope) {
+ if(!credential_scope)
goto fail;
- }
if(Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
- strlen(canonical_request))) {
+ strlen(canonical_request)))
goto fail;
- }
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+ /* provider 0 uppercase */
+ Curl_strntoupper(provider0, provider0, strlen(provider0));
+
/*
- * Google allow to use rsa key instead of HMAC, so this code might change
- * In the future, but for now we support only HMAC version
+ * Google allows using RSA key instead of HMAC, so this code might change
+ * in the future. For now we ony support HMAC.
*/
str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
"%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */
- provider0_up,
+ provider0,
timestamp,
credential_scope,
sha_hex);
@@ -346,36 +474,33 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
goto fail;
}
- secret = curl_maprintf("%s4%s", provider0_up, passwd);
- if(!secret) {
+ /* provider 0 uppercase */
+ secret = curl_maprintf("%s4%s", provider0,
+ data->state.aptr.passwd ?
+ data->state.aptr.passwd : "");
+ if(!secret)
goto fail;
- }
- HMAC_SHA256(secret, strlen(secret),
- date, strlen(date), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- region, strlen(region), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- service, strlen(service), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- request_type, strlen(request_type), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- str_to_sign, strlen(str_to_sign), tmp_sign0);
+ HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), region, strlen(region), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), service, strlen(service), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
- sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+ sha256_to_hex(sha_hex, sign0, sizeof(sha_hex));
+ /* provider 0 uppercase */
auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
"Credential=%s/%s, "
"SignedHeaders=%s, "
"Signature=%s\r\n"
- "X-%s-Date: %s\r\n",
- provider0_up,
+ "%s\r\n",
+ provider0,
user,
credential_scope,
- signed_headers,
+ Curl_dyn_ptr(&signed_headers),
sha_hex,
- provider1_mid,
- timestamp);
+ date_header);
if(!auth_headers) {
goto fail;
}
@@ -386,19 +511,14 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
ret = CURLE_OK;
fail:
- free(provider0_low);
- free(provider0_up);
- free(provider1_low);
- free(provider1_mid);
- free(region);
- free(service);
- free(canonical_headers);
- free(signed_headers);
+ Curl_dyn_free(&canonical_headers);
+ Curl_dyn_free(&signed_headers);
free(canonical_request);
free(request_type);
free(credential_scope);
free(str_to_sign);
free(secret);
+ free(date_header);
return ret;
}
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.h b/Utilities/cmcurl/lib/http_aws_sigv4.h
index 886b31440..85755e937 100644
--- a/Utilities/cmcurl/lib/http_aws_sigv4.h
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index 6bafcd977..0b836851a 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -98,7 +100,7 @@ void Curl_httpchunk_init(struct Curl_easy *data)
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
char *datap,
ssize_t datalen,
- ssize_t *wrotep,
+ ssize_t *wrote,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
@@ -107,7 +109,6 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
struct SingleRequest *k = &data->req;
size_t piece;
curl_off_t length = (curl_off_t)datalen;
- size_t *wrote = (size_t *)wrotep;
*wrote = 0; /* nothing's written yet */
@@ -124,7 +125,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(isxdigit_ascii(*datap)) {
+ if(ISXDIGIT(*datap)) {
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
diff --git a/Utilities/cmcurl/lib/http_chunks.h b/Utilities/cmcurl/lib/http_chunks.h
index 741a9a3bc..2cf5507c2 100644
--- a/Utilities/cmcurl/lib/http_chunks.h
+++ b/Utilities/cmcurl/lib/http_chunks.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
struct connectdata;
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index 34bb5a8e0..a71c6b7cf 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -56,11 +58,11 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
digest = &data->state.digest;
}
- if(!checkprefix("Digest", header) || !ISSPACE(header[6]))
+ if(!checkprefix("Digest", header) || !ISBLANK(header[6]))
return CURLE_BAD_CONTENT_ENCODING;
header += strlen("Digest");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
return Curl_auth_decode_digest_http_message(header, digest);
diff --git a/Utilities/cmcurl/lib/http_digest.h b/Utilities/cmcurl/lib/http_digest.h
index 89438d1a1..eea90b743 100644
--- a/Utilities/cmcurl/lib/http_digest.h
+++ b/Utilities/cmcurl/lib/http_digest.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index 888d3b24a..5909f85b0 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -82,7 +84,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
/* Obtain the input token, if any */
header += strlen("Negotiate");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
len = strlen(header);
diff --git a/Utilities/cmcurl/lib/http_negotiate.h b/Utilities/cmcurl/lib/http_negotiate.h
index 2640a3ee0..6e2096c69 100644
--- a/Utilities/cmcurl/lib/http_negotiate.h
+++ b/Utilities/cmcurl/lib/http_negotiate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index bb7e5360f..5a6a97790 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -27,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
diff --git a/Utilities/cmcurl/lib/http_ntlm.h b/Utilities/cmcurl/lib/http_ntlm.h
index 5b4fa00ba..cec63b82c 100644
--- a/Utilities/cmcurl/lib/http_ntlm.h
+++ b/Utilities/cmcurl/lib/http_ntlm.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index ed08193e1..cc20b3a80 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -210,10 +212,8 @@ void Curl_connect_done(struct Curl_easy *data)
Curl_dyn_free(&s->rcvbuf);
Curl_dyn_free(&s->req);
- /* restore the protocol pointer, if not already done */
- if(s->prot_save)
- data->req.p.http = s->prot_save;
- s->prot_save = NULL;
+ /* restore the protocol pointer */
+ data->req.p.http = s->prot_save;
data->info.httpcode = 0; /* clear it as it might've been used for the
proxy */
data->req.ignorebody = FALSE;
@@ -391,8 +391,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
if(!result)
/* send to debug callback! */
- result = Curl_debug(data, CURLINFO_HEADER_OUT,
- k->upload_fromhere, bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT,
+ k->upload_fromhere, bytes_written);
s->nsend -= bytes_written;
k->upload_fromhere += bytes_written;
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index 67543b589..1e650ee57 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/idn_win32.c b/Utilities/cmcurl/lib/idn_win32.c
index 0914e1f25..2433d927e 100644
--- a/Utilities/cmcurl/lib/idn_win32.c
+++ b/Utilities/cmcurl/lib/idn_win32.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -65,10 +67,10 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
#define IDN_MAX_LENGTH 255
-bool curl_win32_idn_to_ascii(const char *in, char **out);
-bool curl_win32_ascii_to_idn(const char *in, char **out);
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
+bool Curl_win32_ascii_to_idn(const char *in, char **out);
-bool curl_win32_idn_to_ascii(const char *in, char **out)
+bool Curl_win32_idn_to_ascii(const char *in, char **out)
{
bool success = FALSE;
@@ -91,7 +93,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out)
return success;
}
-bool curl_win32_ascii_to_idn(const char *in, char **out)
+bool Curl_win32_ascii_to_idn(const char *in, char **out)
{
bool success = FALSE;
diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index 1d3453193..c29194878 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/if2ip.h b/Utilities/cmcurl/lib/if2ip.h
index a360d4a0e..5d15459e9 100644
--- a/Utilities/cmcurl/lib/if2ip.h
+++ b/Utilities/cmcurl/lib/if2ip.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index 817513bec..ffa08bf7a 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2195 CRAM-MD5 authentication
* RFC2595 Using TLS with IMAP, POP3 and ACAP
* RFC2831 DIGEST-MD5 authentication
@@ -81,6 +83,7 @@
#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
+#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -1883,22 +1886,17 @@ static char *imap_atom(const char *str, bool escape_only)
*/
static bool imap_is_bchar(char ch)
{
+ /* Performing the alnum check with this macro is faster because of ASCII
+ arithmetic */
+ if(ISALNUM(ch))
+ return true;
+
switch(ch) {
/* bchar */
case ':': case '@': case '/':
/* bchar -> achar */
case '&': case '=':
- /* bchar -> achar -> uchar -> unreserved */
- case '0': case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
- case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
- case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
- case 'V': case 'W': case 'X': case 'Y': case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
- case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
- case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z':
+ /* bchar -> achar -> uchar -> unreserved (without alphanumeric) */
case '-': case '.': case '_': case '~':
/* bchar -> achar -> uchar -> sub-delims-sh */
case '!': case '$': case '\'': case '(': case ')': case '*':
diff --git a/Utilities/cmcurl/lib/imap.h b/Utilities/cmcurl/lib/imap.h
index ef6515d8c..43cc1e98f 100644
--- a/Utilities/cmcurl/lib/imap.h
+++ b/Utilities/cmcurl/lib/imap.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "pingpong.h"
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index b5f9b808a..024f8da36 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1996-2021 Internet Software Consortium.
+ * Copyright (C) 1996-2022 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -13,6 +13,8 @@
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * SPDX-License-Identifier: ISC
*/
/*
* Original code by Paul Vixie. "curlified" by Gisle Vanem.
diff --git a/Utilities/cmcurl/lib/inet_ntop.h b/Utilities/cmcurl/lib/inet_ntop.h
index 067632aae..18fbd8ba3 100644
--- a/Utilities/cmcurl/lib/inet_ntop.h
+++ b/Utilities/cmcurl/lib/inet_ntop.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c
index ada57af28..47fb77834 100644
--- a/Utilities/cmcurl/lib/inet_pton.c
+++ b/Utilities/cmcurl/lib/inet_pton.c
@@ -1,6 +1,6 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
-/* Copyright (c) 1996 - 2021 by Internet Software Consortium.
+/* Copyright (c) 2003 - 2022 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,8 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
+ *
+ * SPDX-License-Identifier: ISC
*/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/inet_pton.h b/Utilities/cmcurl/lib/inet_pton.h
index ec1237309..92ae93ea1 100644
--- a/Utilities/cmcurl/lib/inet_pton.h
+++ b/Utilities/cmcurl/lib/inet_pton.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index dee94c92e..1c993c10d 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -5,6 +5,8 @@
* Copyright (c) 2004 - 2022 Daniel Stenberg
* All rights reserved.
*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -140,11 +142,8 @@ krb5_decode(void *app_data, void *buf, int len,
enc.value = buf;
enc.length = len;
maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL);
- if(maj != GSS_S_COMPLETE) {
- if(len >= 4)
- strcpy(buf, "599 ");
+ if(maj != GSS_S_COMPLETE)
return -1;
- }
memcpy(buf, dec.value, dec.length);
len = curlx_uztosi(dec.length);
@@ -506,6 +505,7 @@ static CURLcode read_data(struct connectdata *conn,
{
int len;
CURLcode result;
+ int nread;
result = socket_read(fd, &len, sizeof(len));
if(result)
@@ -514,7 +514,10 @@ static CURLcode read_data(struct connectdata *conn,
if(len) {
/* only realloc if there was a length */
len = ntohl(len);
- buf->data = Curl_saferealloc(buf->data, len);
+ if(len > CURL_MAX_INPUT_LENGTH)
+ len = 0;
+ else
+ buf->data = Curl_saferealloc(buf->data, len);
}
if(!len || !buf->data)
return CURLE_OUT_OF_MEMORY;
@@ -522,8 +525,11 @@ static CURLcode read_data(struct connectdata *conn,
result = socket_read(fd, buf->data, len);
if(result)
return result;
- buf->size = conn->mech->decode(conn->app_data, buf->data, len,
- conn->data_prot, conn);
+ nread = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ if(nread < 0)
+ return CURLE_RECV_ERROR;
+ buf->size = (size_t)nread;
buf->index = 0;
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 03ea14e1f..b07334904 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -35,6 +37,18 @@
* OpenLDAP library versions, USE_OPENLDAP shall not be defined.
*/
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
# include <winldap.h>
# ifndef LDAP_VENDOR_NAME
@@ -342,7 +356,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
#ifdef HAVE_LDAP_SSL
#ifdef USE_WIN32_LDAP
/* Win32 LDAP SDK doesn't support insecure mode without CA! */
- server = ldap_sslinit(host, (int)conn->port, 1);
+ server = ldap_sslinit(host, conn->port, 1);
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
#else
int ldap_option;
@@ -388,9 +402,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- server = ldapssl_init(host, (int)conn->port, 1);
+ server = ldapssl_init(host, conn->port, 1);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
@@ -429,9 +443,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- server = ldap_init(host, (int)conn->port);
+ server = ldap_init(host, conn->port);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
@@ -470,9 +484,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
else {
- server = ldap_init(host, (int)conn->port);
+ server = ldap_init(host, conn->port);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
diff --git a/Utilities/cmcurl/lib/libcurl.rc b/Utilities/cmcurl/lib/libcurl.rc
index fde6c8cae..23134a710 100644
--- a/Utilities/cmcurl/lib/libcurl.rc
+++ b/Utilities/cmcurl/lib/libcurl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <winver.h>
#include "../include/curl/curlver.h"
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index e78da7da8..fa2d366cb 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index ceae2dd1b..2fcb91ca5 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 117cce4fd..e976fe7bd 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -30,7 +32,8 @@
#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
+ !defined(USE_AMISSL)
/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
#define OPENSSL_NO_MD4
#endif
@@ -39,7 +42,7 @@
#ifdef USE_WOLFSSL
#include <wolfssl/options.h>
#ifdef NO_MD4
-#define OPENSSL_NO_MD4
+#define WOLFSSL_NO_MD4
#endif
#endif
@@ -82,9 +85,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
md4_digest(ctx, MD4_DIGEST_SIZE, result);
}
-#elif (defined(USE_OPENSSL) || defined(USE_WOLFSSL)) && \
- !defined(OPENSSL_NO_MD4)
/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
+#elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
+#include <wolfssl/openssl/md4.h>
+
+#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
#include <openssl/md4.h>
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index d2ca240fc..5be639929 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -39,7 +41,7 @@
#endif
#endif /* USE_MBEDTLS */
-#if defined(USE_OPENSSL) && !defined(USE_AMISSL)
+#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
#define USE_OPENSSL_MD5
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index 050c5d4b2..15fb49155 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -127,7 +129,8 @@ static bool countcheck(const char *func, int line, const char *source)
return FALSE; /* allow this */
}
-void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
+ALLOC_FUNC void *curl_dbg_malloc(size_t wantedsize,
+ int line, const char *source)
{
struct memdebug *mem;
size_t size;
@@ -153,8 +156,8 @@ void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
return (mem ? mem->mem : NULL);
}
-void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
- int line, const char *source)
+ALLOC_FUNC void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
+ int line, const char *source)
{
struct memdebug *mem;
size_t size, user_size;
@@ -181,7 +184,8 @@ void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
return (mem ? mem->mem : NULL);
}
-char *curl_dbg_strdup(const char *str, int line, const char *source)
+ALLOC_FUNC char *curl_dbg_strdup(const char *str,
+ int line, const char *source)
{
char *mem;
size_t len;
@@ -205,7 +209,8 @@ char *curl_dbg_strdup(const char *str, int line, const char *source)
}
#if defined(WIN32) && defined(UNICODE)
-wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source)
+ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
+ int line, const char *source)
{
wchar_t *mem;
size_t wsiz, bsiz;
@@ -408,8 +413,8 @@ int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source)
return res;
}
-FILE *curl_dbg_fopen(const char *file, const char *mode,
- int line, const char *source)
+ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode,
+ int line, const char *source)
{
FILE *res = fopen(file, mode);
@@ -420,8 +425,8 @@ FILE *curl_dbg_fopen(const char *file, const char *mode,
return res;
}
-FILE *curl_dbg_fdopen(int filedes, const char *mode,
- int line, const char *source)
+ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode,
+ int line, const char *source)
{
FILE *res = fdopen(filedes, mode);
if(source)
diff --git a/Utilities/cmcurl/lib/memdebug.h b/Utilities/cmcurl/lib/memdebug.h
index 8e88cea58..7fc90e83a 100644
--- a/Utilities/cmcurl/lib/memdebug.h
+++ b/Utilities/cmcurl/lib/memdebug.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -28,21 +30,44 @@
* as well as the library. Do not mix with library internals!
*/
+#include <curl/curl.h>
+#include "functypes.h"
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+# define ALLOC_FUNC __attribute__((malloc))
+# define ALLOC_SIZE(s) __attribute__((alloc_size(s)))
+# define ALLOC_SIZE2(n, s) __attribute__((alloc_size(n, s)))
+#elif defined(_MSC_VER)
+# define ALLOC_FUNC __declspec(restrict)
+# define ALLOC_SIZE(s)
+# define ALLOC_SIZE2(n, s)
+#else
+# define ALLOC_FUNC
+# define ALLOC_SIZE(s)
+# define ALLOC_SIZE2(n, s)
+#endif
+
#define CURL_MT_LOGFNAME_BUFSIZE 512
extern FILE *curl_dbg_logfile;
/* memory functions */
-CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source);
-CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line,
- const char *source);
-CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line,
- const char *source);
+CURL_EXTERN ALLOC_FUNC ALLOC_SIZE(1) void *curl_dbg_malloc(size_t size,
+ int line,
+ const char *source);
+CURL_EXTERN ALLOC_FUNC ALLOC_SIZE2(1, 2) void *curl_dbg_calloc(size_t elements,
+ size_t size, int line, const char *source);
+CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
+ size_t size,
+ int line,
+ const char *source);
CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
-CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src);
+CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
+ const char *src);
#if defined(WIN32) && defined(UNICODE)
-CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line,
- const char *source);
+CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
+ int line,
+ const char *source);
#endif
CURL_EXTERN void curl_dbg_memdebug(const char *logname);
@@ -77,10 +102,10 @@ CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd,
const char *source);
/* FILE functions */
-CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
- const char *source);
-CURL_EXTERN FILE *curl_dbg_fdopen(int filedes, const char *mode,
+CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode,
int line, const char *source);
+CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode,
+ int line, const char *source);
CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index d6985d39c..042141fc8 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -29,8 +31,9 @@
#include "urldata.h"
#include "sendf.h"
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
@@ -1922,8 +1925,8 @@ void Curl_mime_unpause(curl_mimepart *part)
}
-#else /* !CURL_DISABLE_HTTP && !CURL_DISABLE_MIME ||
- !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
+ !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
/* Mime not compiled in: define stubs for externally-referenced functions. */
curl_mime *curl_mime_init(CURL *easy)
diff --git a/Utilities/cmcurl/lib/mime.h b/Utilities/cmcurl/lib/mime.h
index f2fc434c5..bafde29f4 100644
--- a/Utilities/cmcurl/lib/mime.h
+++ b/Utilities/cmcurl/lib/mime.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -132,8 +134,9 @@ struct curl_mimepart {
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
/* Prototypes. */
void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 13812010b..8a7c17a7f 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
*
* Purpose:
* A merge of Bjorn Reese's format() function and Daniel's dsprintf()
@@ -316,6 +318,11 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
flags |= FLAGS_PREC;
precision = strtol(fmt, &fmt, 10);
}
+ if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
+ (FLAGS_PREC | FLAGS_PRECPARAM))
+ /* it is not permitted to use both kinds of precision for the same
+ argument */
+ return 1;
break;
case 'h':
flags |= FLAGS_SHORT;
@@ -592,7 +599,7 @@ static int dprintf_formatf(
/* Do the actual %-code parsing */
if(dprintf_Pass1(format, vto, endpos, ap_save))
- return -1;
+ return 0;
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
@@ -954,11 +961,22 @@ static int dprintf_formatf(
else
*fptr++ = 'f';
- *fptr = 0; /* and a final zero termination */
+ *fptr = 0; /* and a final null-termination */
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
+#ifdef HAVE_SNPRINTF
+ (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
+#else
(sprintf)(work, formatbuf, p->data.dnum);
+#endif
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
DEBUGASSERT(strlen(work) <= sizeof(work));
for(fptr = work; *fptr; fptr++)
OUTCHAR(*fptr);
@@ -1016,11 +1034,12 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
- if((retcode != -1) && info.max) {
+ if(info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length) {
/* we're at maximum, scrap the last letter */
info.buffer[-1] = 0;
+ DEBUGASSERT(retcode);
retcode--; /* don't count the nul byte */
}
else
@@ -1058,13 +1077,12 @@ extern int Curl_dyn_vprintf(struct dynbuf *dyn,
/* appends the formatted string, returns 0 on success, 1 on error */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
- int retcode;
struct asprintf info;
info.b = dyn;
info.fail = 0;
- retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if((-1 == retcode) || info.fail) {
+ (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.fail) {
Curl_dyn_free(info.b);
return 1;
}
@@ -1073,15 +1091,14 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
char *curl_mvaprintf(const char *format, va_list ap_save)
{
- int retcode;
struct asprintf info;
struct dynbuf dyn;
info.b = &dyn;
Curl_dyn_init(info.b, DYN_APRINTF);
info.fail = 0;
- retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if((-1 == retcode) || info.fail) {
+ (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.fail) {
Curl_dyn_free(info.b);
return NULL;
}
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index 9bcbaa195..4f3d14386 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -184,7 +186,7 @@ static int add_passwd(const char *passwd, const size_t plen,
return 0;
}
-/* add user to the CONN packet */
+/* add user to the CONNECT packet */
static int add_user(const char *username, const size_t ulen,
unsigned char *pkt, const size_t start, int remain_pos)
{
@@ -202,7 +204,7 @@ static int add_user(const char *username, const size_t ulen,
return 0;
}
-/* add client ID to the CONN packet */
+/* add client ID to the CONNECT packet */
static int add_client_id(const char *client_id, const size_t client_id_len,
char *pkt, const size_t start)
{
@@ -214,7 +216,7 @@ static int add_client_id(const char *client_id, const size_t client_id_len,
return 0;
}
-/* Set initial values of CONN packet */
+/* Set initial values of CONNECT packet */
static int init_connpack(char *packet, char *remain, int remain_pos)
{
/* Fixed header starts */
@@ -291,7 +293,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
memset(packet, 0, packetlen);
- /* set initial values for CONN pack */
+ /* set initial values for the CONNECT packet */
pos = init_connpack(packet, remain, remain_pos);
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
@@ -387,10 +389,18 @@ static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen)
{
char *path = data->state.up.path;
- if(strlen(path) > 1)
- return Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
- failf(data, "No MQTT topic found. Forgot to URL encode it?");
- return CURLE_URL_MALFORMAT;
+ CURLcode result = CURLE_URL_MALFORMAT;
+ if(strlen(path) > 1) {
+ result = Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
+ if(!result && (*topiclen > 0xffff)) {
+ failf(data, "Too long MQTT topic");
+ result = CURLE_URL_MALFORMAT;
+ }
+ }
+ else
+ failf(data, "No MQTT topic found. Forgot to URL encode it?");
+
+ return result;
}
static CURLcode mqtt_subscribe(struct Curl_easy *data)
@@ -688,7 +698,7 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
result = mqtt_connect(data);
if(result) {
- failf(data, "Error %d sending MQTT CONN request", result);
+ failf(data, "Error %d sending MQTT CONNECT request", result);
return result;
}
mqstate(data, MQTT_FIRST, MQTT_CONNACK);
diff --git a/Utilities/cmcurl/lib/mqtt.h b/Utilities/cmcurl/lib/mqtt.h
index fb52c7232..c400d9b14 100644
--- a/Utilities/cmcurl/lib/mqtt.h
+++ b/Utilities/cmcurl/lib/mqtt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Björn Stenberg, <bjorn@haxx.se>
+ * Copyright (C) 2019 - 2022, Björn Stenberg, <bjorn@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_MQTT
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 8e58d785a..51acba73a 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -43,7 +45,6 @@
#include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
-#include "connect.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -53,6 +54,22 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef __APPLE__
+
+#define wakeup_write write
+#define wakeup_read read
+#define wakeup_close close
+#define wakeup_create pipe
+
+#else /* __APPLE__ */
+
+#define wakeup_write swrite
+#define wakeup_read sread
+#define wakeup_close sclose
+#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
+
+#endif /* __APPLE__ */
+
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -66,6 +83,10 @@
#define CURL_CONNECTION_HASH_SIZE 97
#endif
+#ifndef CURL_DNS_HASH_SIZE
+#define CURL_DNS_HASH_SIZE 71
+#endif
+
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
@@ -370,7 +391,8 @@ static CURLMcode multi_addmsg(struct Curl_multi *multi,
}
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
- int chashsize) /* connection hash */
+ int chashsize, /* connection hash */
+ int dnssize) /* dns hash */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -379,7 +401,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
multi->magic = CURL_MULTI_HANDLE;
- Curl_init_dnscache(&multi->hostcache);
+ Curl_init_dnscache(&multi->hostcache, dnssize);
sh_init(&multi->sockhash, hashsize);
@@ -394,7 +416,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
- multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
@@ -402,14 +423,14 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
goto error;
#else
#ifdef ENABLE_WAKEUP
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
+ if(wakeup_create(multi->wakeup_pair) < 0) {
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
@@ -433,7 +454,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
struct Curl_multi *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
- CURL_CONNECTION_HASH_SIZE);
+ CURL_CONNECTION_HASH_SIZE,
+ CURL_DNS_HASH_SIZE);
}
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
@@ -627,7 +649,7 @@ static CURLcode multi_done(struct Curl_easy *data,
if(CURLE_ABORTED_BY_CALLBACK != result) {
/* avoid this if we already aborted by callback to avoid this calling
another callback */
- CURLcode rc = Curl_pgrsDone(data);
+ int rc = Curl_pgrsDone(data);
if(!result && rc)
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -729,7 +751,7 @@ static int close_connect_only(struct Curl_easy *data,
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(!conn->bits.connect_only)
+ if(!conn->connect_only)
return 1;
connclose(conn, "Removing connect-only easy handle");
@@ -826,6 +848,24 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Remove the association between the connection and the handle */
Curl_detach_connection(data);
+ if(data->set.connect_only && !data->multi_easy) {
+ /* This removes a handle that was part the multi interface that used
+ CONNECT_ONLY, that connection is now left alive but since this handle
+ has bits.close set nothing can use that transfer anymore and it is
+ forbidden from reuse. And this easy handle cannot find the connection
+ anymore once removed from the multi handle
+
+ Better close the connection here, at once.
+ */
+ struct connectdata *c;
+ curl_socket_t s;
+ s = Curl_getconnectinfo(data, &c);
+ if((s != CURL_SOCKET_BAD) && c) {
+ Curl_conncache_remove_conn(data, c, TRUE);
+ Curl_disconnect(data, c, TRUE);
+ }
+ }
+
if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
@@ -1307,16 +1347,19 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
else
pollrc = 0;
- if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
- WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
#else
pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
#endif
+ if(pollrc < 0)
+ return CURLM_UNRECOVERABLE_POLL;
if(pollrc > 0) {
retcode = pollrc;
#ifdef USE_WINSOCK
}
+ else { /* now wait... if not ready during the pre-check (pollrc == 0) */
+ WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
+ }
/* With WinSock, we have to run the following section unconditionally
to call WSAEventSelect(fd, event, 0) on all the sockets */
{
@@ -1328,20 +1371,23 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
unsigned r = ufds[curlfds + i].revents;
unsigned short mask = 0;
#ifdef USE_WINSOCK
+ curl_socket_t s = extra_fds[i].fd;
wsa_events.lNetworkEvents = 0;
- if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
+ if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
mask |= CURL_WAIT_POLLIN;
if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
mask |= CURL_WAIT_POLLOUT;
if(wsa_events.lNetworkEvents & FD_OOB)
mask |= CURL_WAIT_POLLPRI;
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
- WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
- if(pollrc <= 0)
+ WSAEventSelect(s, multi->wsa_event, 0);
+ if(!pollrc) {
+ extra_fds[i].revents = mask;
continue;
+ }
#endif
if(r & POLLIN)
mask |= CURL_WAIT_POLLIN;
@@ -1364,7 +1410,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
wsa_events.lNetworkEvents = 0;
if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
@@ -1391,7 +1437,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
data from it until it receives an error (except EINTR).
In normal cases it will get EAGAIN or EWOULDBLOCK
when there is no more data, breaking the loop. */
- nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
+ nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
if(nread <= 0) {
if(nread < 0 && EINTR == SOCKERRNO)
continue;
@@ -1484,7 +1530,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
that will call curl_multi_wait(). If swrite() returns that it
would block, it's considered successful because it means that
previous calls to this function will wake up the poll(). */
- if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
+ if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
int err = SOCKERRNO;
int return_success;
#ifdef USE_WINSOCK
@@ -2096,7 +2142,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
- if(data->set.connect_only) {
+ if(data->set.connect_only == 1) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
@@ -2720,8 +2766,8 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
WSACloseEvent(multi->wsa_event);
#else
#ifdef ENABLE_WAKEUP
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
#endif
#endif
free(multi);
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index db7f130ef..a997784ea 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "llist.h"
@@ -148,11 +150,13 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
- /* multiplexing wanted */
- bool multiplexing;
- bool recheckstate; /* see Curl_multi_connchanged */
+#define IPV6_UNKNOWN 0
+#define IPV6_DEAD 1
+#define IPV6_WORKS 2
+ unsigned char ipv6_up; /* IPV6_* defined */
+ bool multiplexing; /* multiplexing wanted */
+ bool recheckstate; /* see Curl_multi_connchanged */
bool in_callback; /* true while executing a callback */
- bool ipv6_works;
#ifdef USE_OPENSSL
bool ssl_seeded;
#endif
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index 5a8c358bc..0cb9d4f7f 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -40,8 +42,9 @@ bool Curl_is_in_callback(struct Curl_easy *easy);
CURLcode Curl_preconnect(struct Curl_easy *data);
/* Internal version of curl_multi_init() accepts size parameters for the
- socket and connection hashes */
-struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
+ socket, connection and dns hashes */
+struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
+ int dnssize);
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
diff --git a/Utilities/cmcurl/lib/netrc.c b/Utilities/cmcurl/lib/netrc.c
index 0a4ae2cdc..4461b8492 100644
--- a/Utilities/cmcurl/lib/netrc.c
+++ b/Utilities/cmcurl/lib/netrc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -31,6 +33,7 @@
#include "netrc.h"
#include "strtok.h"
#include "strcase.h"
+#include "curl_get_line.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -56,8 +59,6 @@ enum host_lookup_state {
static int parsenetrc(const char *host,
char **loginp,
char **passwordp,
- bool *login_changed,
- bool *password_changed,
char *netrcfile)
{
FILE *file;
@@ -71,31 +72,87 @@ static int parsenetrc(const char *host,
char state_login = 0; /* Found a login keyword */
char state_password = 0; /* Found a password keyword */
- int state_our_login = FALSE; /* With specific_login, found *our* login
- name */
+ int state_our_login = TRUE; /* With specific_login, found *our* login
+ name (or login-less line) */
DEBUGASSERT(netrcfile);
file = fopen(netrcfile, FOPEN_READTEXT);
if(file) {
- char *tok;
- char *tok_buf;
bool done = FALSE;
char netrcbuffer[4096];
int netrcbuffsize = (int)sizeof(netrcbuffer);
- while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
+ char *tok;
+ char *tok_end;
+ bool quoted;
if(state == MACDEF) {
if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
state = NOTHING;
else
continue;
}
- tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
- if(tok && *tok == '#')
- /* treat an initial hash as a comment line */
- continue;
+ tok = netrcbuffer;
while(tok) {
+ while(ISBLANK(*tok))
+ tok++;
+ /* tok is first non-space letter */
+ if(!*tok || (*tok == '#'))
+ /* end of line or the rest is a comment */
+ break;
+
+ /* leading double-quote means quoted string */
+ quoted = (*tok == '\"');
+
+ tok_end = tok;
+ if(!quoted) {
+ while(!ISSPACE(*tok_end))
+ tok_end++;
+ *tok_end = 0;
+ }
+ else {
+ bool escape = FALSE;
+ bool endquote = FALSE;
+ char *store = tok;
+ tok_end++; /* pass the leading quote */
+ while(*tok_end) {
+ char s = *tok_end;
+ if(escape) {
+ escape = FALSE;
+ switch(s) {
+ case 'n':
+ s = '\n';
+ break;
+ case 'r':
+ s = '\r';
+ break;
+ case 't':
+ s = '\t';
+ break;
+ }
+ }
+ else if(s == '\\') {
+ escape = TRUE;
+ tok_end++;
+ continue;
+ }
+ else if(s == '\"') {
+ tok_end++; /* pass the ending quote */
+ endquote = TRUE;
+ break;
+ }
+ *store++ = s;
+ tok_end++;
+ }
+ *store = 0;
+ if(escape || !endquote) {
+ /* bad syntax, get out */
+ retcode = NETRC_FAILED;
+ goto out;
+ }
+ }
+
if((login && *login) && (password && *password)) {
done = TRUE;
break;
@@ -140,9 +197,9 @@ static int parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = strcasecompare(login, tok);
+ state_our_login = !Curl_timestrcmp(login, tok);
}
- else if(!login || strcmp(login, tok)) {
+ else if(!login || Curl_timestrcmp(login, tok)) {
if(login_alloc) {
free(login);
login_alloc = FALSE;
@@ -158,7 +215,7 @@ static int parsenetrc(const char *host,
}
else if(state_password) {
if((state_our_login || !specific_login)
- && (!password || strcmp(password, tok))) {
+ && (!password || Curl_timestrcmp(password, tok))) {
if(password_alloc) {
free(password);
password_alloc = FALSE;
@@ -183,27 +240,22 @@ static int parsenetrc(const char *host,
}
break;
} /* switch (state) */
-
- tok = strtok_r(NULL, " \t\n", &tok_buf);
- } /* while(tok) */
- } /* while fgets() */
+ tok = ++tok_end;
+ }
+ } /* while Curl_get_line() */
out:
if(!retcode) {
/* success */
- *login_changed = FALSE;
- *password_changed = FALSE;
if(login_alloc) {
if(*loginp)
free(*loginp);
*loginp = login;
- *login_changed = TRUE;
}
if(password_alloc) {
if(*passwordp)
free(*passwordp);
*passwordp = password;
- *password_changed = TRUE;
}
}
else {
@@ -224,17 +276,16 @@ static int parsenetrc(const char *host,
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
* in.
*/
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
+int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
char *netrcfile)
{
int retcode = 1;
char *filealloc = NULL;
if(!netrcfile) {
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ char pwbuf[1024];
+#endif
char *home = NULL;
char *homea = curl_getenv("HOME"); /* portable environment reader */
if(homea) {
@@ -243,7 +294,6 @@ int Curl_parsenetrc(const char *host,
}
else {
struct passwd pw, *pw_res;
- char pwbuf[1024];
if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
&& pw_res) {
home = pw.pw_dir;
@@ -256,6 +306,13 @@ int Curl_parsenetrc(const char *host,
if(pw) {
home = pw->pw_dir;
}
+#elif defined(_WIN32)
+ }
+ else {
+ homea = curl_getenv("USERPROFILE");
+ if(homea) {
+ home = homea;
+ }
#endif
}
@@ -268,8 +325,7 @@ int Curl_parsenetrc(const char *host,
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
#ifdef WIN32
if(retcode == NETRC_FILE_MISSING) {
@@ -279,16 +335,14 @@ int Curl_parsenetrc(const char *host,
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
}
#endif
free(homea);
}
else
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, netrcfile);
+ retcode = parsenetrc(host, loginp, passwordp, netrcfile);
return retcode;
}
diff --git a/Utilities/cmcurl/lib/netrc.h b/Utilities/cmcurl/lib/netrc.h
index 4938a5916..53d005672 100644
--- a/Utilities/cmcurl/lib/netrc.h
+++ b/Utilities/cmcurl/lib/netrc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,18 +20,16 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DISABLE_NETRC
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
- char *filename);
+int Curl_parsenetrc(const char *host, char **loginp,
+ char **passwordp, char *filename);
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine
* section in the netrc.
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index 28f6e7588..ce73af31c 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/nonblock.h b/Utilities/cmcurl/lib/nonblock.h
index 761dab4f6..a42f443a4 100644
--- a/Utilities/cmcurl/lib/nonblock.h
+++ b/Utilities/cmcurl/lib/nonblock.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h> /* for curl_socket_t */
diff --git a/Utilities/cmcurl/lib/noproxy.c b/Utilities/cmcurl/lib/noproxy.c
new file mode 100644
index 000000000..81f1e0993
--- /dev/null
+++ b/Utilities/cmcurl/lib/noproxy.c
@@ -0,0 +1,222 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#include "inet_pton.h"
+#include "strcase.h"
+#include "noproxy.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/*
+ * Curl_cidr4_match() returns TRUE if the given IPv4 address is within the
+ * specified CIDR address range.
+ */
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits)
+{
+ unsigned int address = 0;
+ unsigned int check = 0;
+
+ if(bits > 32)
+ /* strange input */
+ return FALSE;
+
+ if(1 != Curl_inet_pton(AF_INET, ipv4, &address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET, network, &check))
+ return FALSE;
+
+ if(bits && (bits != 32)) {
+ unsigned int mask = 0xffffffff << (32 - bits);
+ unsigned int haddr = htonl(address);
+ unsigned int hcheck = htonl(check);
+#if 0
+ fprintf(stderr, "Host %s (%x) network %s (%x) bits %u mask %x => %x\n",
+ ipv4, haddr, network, hcheck, bits, mask,
+ (haddr ^ hcheck) & mask);
+#endif
+ if((haddr ^ hcheck) & mask)
+ return FALSE;
+ return TRUE;
+ }
+ return (address == check);
+}
+
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits)
+{
+#ifdef ENABLE_IPV6
+ int bytes;
+ int rest;
+ unsigned char address[16];
+ unsigned char check[16];
+
+ if(!bits)
+ bits = 128;
+
+ bytes = bits/8;
+ rest = bits & 0x07;
+ if(1 != Curl_inet_pton(AF_INET6, ipv6, address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET6, network, check))
+ return FALSE;
+ if((bytes > 16) || ((bytes == 16) && rest))
+ return FALSE;
+ if(bytes && memcmp(address, check, bytes))
+ return FALSE;
+ if(rest && !((address[bytes] ^ check[bytes]) & (0xff << (8 - rest))))
+ return FALSE;
+
+ return TRUE;
+#else
+ (void)ipv6;
+ (void)network;
+ (void)bits;
+ return FALSE;
+#endif
+}
+
+enum nametype {
+ TYPE_HOST,
+ TYPE_IPV4,
+ TYPE_IPV6
+};
+
+/****************************************************************
+* Checks if the host is in the noproxy list. returns TRUE if it matches and
+* therefore the proxy should NOT be used.
+****************************************************************/
+bool Curl_check_noproxy(const char *name, const char *no_proxy)
+{
+ /* no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ */
+ if(no_proxy && no_proxy[0]) {
+ const char *p = no_proxy;
+ size_t namelen;
+ enum nametype type = TYPE_HOST;
+ char hostip[128];
+ if(!strcmp("*", no_proxy))
+ return TRUE;
+
+ /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ if(name[0] == '[') {
+ char *endptr;
+ /* IPv6 numerical address */
+ endptr = strchr(name, ']');
+ if(!endptr)
+ return FALSE;
+ name++;
+ namelen = endptr - name;
+ if(namelen >= sizeof(hostip))
+ return FALSE;
+ memcpy(hostip, name, namelen);
+ hostip[namelen] = 0;
+ name = hostip;
+ type = TYPE_IPV6;
+ }
+ else {
+ unsigned int address;
+ if(1 == Curl_inet_pton(AF_INET, name, &address))
+ type = TYPE_IPV4;
+ namelen = strlen(name);
+ }
+
+ while(*p) {
+ const char *token;
+ size_t tokenlen = 0;
+ bool match = FALSE;
+
+ /* pass blanks */
+ while(*p && ISBLANK(*p))
+ p++;
+
+ token = p;
+ /* pass over the pattern */
+ while(*p && !ISBLANK(*p) && (*p != ',')) {
+ p++;
+ tokenlen++;
+ }
+
+ if(tokenlen) {
+ switch(type) {
+ case TYPE_HOST:
+ if(*token == '.') {
+ ++token;
+ --tokenlen;
+ /* tailmatch */
+ match = (tokenlen <= namelen) &&
+ strncasecompare(token, name + (namelen - tokenlen), namelen);
+ }
+ else
+ match = (tokenlen == namelen) &&
+ strncasecompare(token, name, namelen);
+ break;
+ case TYPE_IPV4:
+ /* FALLTHROUGH */
+ case TYPE_IPV6: {
+ const char *check = token;
+ char *slash = strchr(check, '/');
+ unsigned int bits = 0;
+ char checkip[128];
+ /* if the slash is part of this token, use it */
+ if(slash && (slash < &check[tokenlen])) {
+ bits = atoi(slash + 1);
+ /* copy the check name to a temp buffer */
+ if(tokenlen >= sizeof(checkip))
+ break;
+ memcpy(checkip, check, tokenlen);
+ checkip[ slash - check ] = 0;
+ check = checkip;
+ }
+ if(type == TYPE_IPV6)
+ match = Curl_cidr6_match(name, check, bits);
+ else
+ match = Curl_cidr4_match(name, check, bits);
+ break;
+ }
+ }
+ if(match)
+ return TRUE;
+ } /* if(tokenlen) */
+ while(*p == ',')
+ p++;
+ } /* while(*p) */
+ } /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ return FALSE;
+}
+
+#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/dotdot.h b/Utilities/cmcurl/lib/noproxy.h
index ac1ea363e..8800a2127 100644
--- a/Utilities/cmcurl/lib/dotdot.h
+++ b/Utilities/cmcurl/lib/noproxy.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_DOTDOT_H
-#define HEADER_CURL_DOTDOT_H
+#ifndef HEADER_CURL_NOPROXY_H
+#define HEADER_CURL_NOPROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,25 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
-char *Curl_dedotdotify(const char *input);
-#endif /* HEADER_CURL_DOTDOT_H */
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#ifdef DEBUGBUILD
+
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits);
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits);
+#endif
+
+bool Curl_check_noproxy(const char *name, const char *no_proxy);
+
+#endif
+
+#endif /* HEADER_CURL_NOPROXY_H */
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index 4e9256770..3a93b6728 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -1066,8 +1068,8 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
if(!binary) {
/* check for leading or trailing whitespace */
- if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len - 1]))
+ if(ISBLANK(bvals[i].bv_val[0]) ||
+ ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1]))
binval = 1;
else {
/* check for unprintable characters */
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c
index 3c38f2c4c..5ed88195f 100644
--- a/Utilities/cmcurl/lib/parsedate.c
+++ b/Utilities/cmcurl/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
A brief summary of the date string formats this parser groks:
diff --git a/Utilities/cmcurl/lib/parsedate.h b/Utilities/cmcurl/lib/parsedate.h
index a99faf9e3..4e4347754 100644
--- a/Utilities/cmcurl/lib/parsedate.h
+++ b/Utilities/cmcurl/lib/parsedate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
extern const char * const Curl_wkday[7];
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index e08c1d866..d4e6be98c 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* 'pingpong' is for generic back-and-forth support functions used by FTP,
* IMAP, POP3, SMTP and whatever more that likes them.
*
@@ -328,7 +330,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
else if(gotbytes <= 0) {
keepon = FALSE;
result = CURLE_RECV_ERROR;
- failf(data, "response reading failed");
+ failf(data, "response reading failed (errno: %d)", SOCKERRNO);
}
else {
/* we got a whole chunk of data, which can be anything from one
@@ -396,7 +398,8 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
}
else if(keepon) {
- if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
+ if((perline == gotbytes) &&
+ (gotbytes > (ssize_t)data->set.buffer_size/2)) {
/* We got an excessive line without newlines and we need to deal
with it. We keep the first bytes of the line then we throw
away the rest. */
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index 8f56f3f86..cefae073a 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 2c1b06c07..3151a3f56 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC1734 POP3 Authentication
* RFC1939 POP3 protocol
* RFC2195 CRAM-MD5 authentication
diff --git a/Utilities/cmcurl/lib/pop3.h b/Utilities/cmcurl/lib/pop3.h
index 17629ee2d..bb0645f9b 100644
--- a/Utilities/cmcurl/lib/pop3.h
+++ b/Utilities/cmcurl/lib/pop3.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "pingpong.h"
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index f5ef6bd52..4a1e1daa8 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index ac4ebc098..a12931514 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "timeval.h"
diff --git a/Utilities/cmcurl/lib/psl.c b/Utilities/cmcurl/lib/psl.c
index e46091863..60c98a4ca 100644
--- a/Utilities/cmcurl/lib/psl.c
+++ b/Utilities/cmcurl/lib/psl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/psl.h b/Utilities/cmcurl/lib/psl.h
index c10367471..34f0a5cae 100644
--- a/Utilities/cmcurl/lib/psl.h
+++ b/Utilities/cmcurl/lib/psl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef USE_LIBPSL
diff --git a/Utilities/cmcurl/lib/quic.h b/Utilities/cmcurl/lib/quic.h
index f92720f5d..b35774735 100644
--- a/Utilities/cmcurl/lib/quic.h
+++ b/Utilities/cmcurl/lib/quic.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -54,6 +56,7 @@ void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
void Curl_quic_disconnect(struct Curl_easy *data,
struct connectdata *conn, int tempindex);
+CURLcode Curl_quic_idle(struct Curl_easy *data);
#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index 8da1e8d96..2e7e7e823 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -36,6 +38,64 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef WIN32
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+# define HAVE_MINGW_ORIGINAL
+#endif
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
+ !defined(HAVE_MINGW_ORIGINAL)
+# define HAVE_WIN_BCRYPTGENRANDOM
+# include <bcrypt.h>
+# ifdef _MSC_VER
+# pragma comment(lib, "bcrypt.lib")
+# endif
+# ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG
+# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
+# endif
+# ifndef STATUS_SUCCESS
+# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+# endif
+#elif defined(USE_WIN32_CRYPTO)
+# include <wincrypt.h>
+# ifdef _MSC_VER
+# pragma comment(lib, "advapi32.lib")
+# endif
+#endif
+
+CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
+{
+ memset(entropy, 0, length);
+
+#if defined(HAVE_WIN_BCRYPTGENRANDOM)
+ if(BCryptGenRandom(NULL, entropy, (ULONG)length,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG) != STATUS_SUCCESS)
+ return CURLE_FAILED_INIT;
+
+ return CURLE_OK;
+#elif defined(USE_WIN32_CRYPTO)
+ {
+ HCRYPTPROV hCryptProv = 0;
+
+ if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return CURLE_FAILED_INIT;
+
+ if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
+ CryptReleaseContext(hCryptProv, 0UL);
+ return CURLE_FAILED_INIT;
+ }
+
+ CryptReleaseContext(hCryptProv, 0UL);
+ }
+ return CURLE_OK;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+#endif
+
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
{
unsigned int r;
@@ -71,7 +131,15 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
/* ---- non-cryptographic version following ---- */
-#ifdef RANDOM_FILE
+#ifdef WIN32
+ if(!seeded) {
+ result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
+ if(result != CURLE_NOT_BUILT_IN)
+ return result;
+ }
+#endif
+
+#if defined(RANDOM_FILE) && !defined(WIN32)
if(!seeded) {
/* if there's a random file to read a seed from, use it */
int fd = open(RANDOM_FILE, O_RDONLY);
@@ -106,7 +174,8 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
* 'rndptr' points to.
*
* If libcurl is built without TLS support or with a TLS backend that lacks a
- * proper random API (Gskit or mbedTLS), this function will use "weak" random.
+ * proper random API (rustls, Gskit or mbedTLS), this function will use "weak"
+ * random.
*
* When built *with* TLS support and a backend that offers strong random, it
* will return error if it cannot provide strong random values.
@@ -143,7 +212,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
* size.
*/
@@ -166,7 +235,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
/* make sure it fits in the local buffer and that it is an odd number! */
return CURLE_BAD_FUNCTION_ARGUMENT;
- num--; /* save one for zero termination */
+ num--; /* save one for null-termination */
result = Curl_rand(data, buffer, num/2);
if(result)
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
index 02d95d8e6..30fc29615 100644
--- a/Utilities/cmcurl/lib/rand.h
+++ b/Utilities/cmcurl/lib/rand.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -40,10 +42,16 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
* size.
*/
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
size_t num);
+#ifdef WIN32
+/* Random generator shared between the Schannel vtls and Curl_rand*()
+ functions */
+CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
+#endif
+
#endif /* HEADER_CURL_RAND_H */
diff --git a/Utilities/cmcurl/lib/rename.c b/Utilities/cmcurl/lib/rename.c
index f858d4369..cfb3699fb 100644
--- a/Utilities/cmcurl/lib/rename.c
+++ b/Utilities/cmcurl/lib/rename.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "rename.h"
diff --git a/Utilities/cmcurl/lib/rename.h b/Utilities/cmcurl/lib/rename.h
index 534f7471c..9958e2cd2 100644
--- a/Utilities/cmcurl/lib/rename.h
+++ b/Utilities/cmcurl/lib/rename.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
int Curl_rename(const char *oldpath, const char *newpath);
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 726bfb9ae..6d3bf97e6 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -792,7 +794,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
/* Find the first non-space letter */
start = header + 8;
- while(*start && ISSPACE(*start))
+ while(*start && ISBLANK(*start))
start++;
if(!*start) {
diff --git a/Utilities/cmcurl/lib/rtsp.h b/Utilities/cmcurl/lib/rtsp.h
index da11ade04..377c82860 100644
--- a/Utilities/cmcurl/lib/rtsp.h
+++ b/Utilities/cmcurl/lib/rtsp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifdef USE_HYPER
#define CURL_DISABLE_RTSP 1
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index a48da82ba..2ac074677 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -308,8 +310,12 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
else
pending_ms = 0;
r = poll(ufds, nfds, pending_ms);
- if(r <= 0)
+ if(r <= 0) {
+ if((r == -1) && (SOCKERRNO == EINTR))
+ /* make EINTR from select or poll not a "lethal" error */
+ r = 0;
return r;
+ }
for(i = 0; i < nfds; i++) {
if(ufds[i].fd == CURL_SOCKET_BAD)
@@ -352,8 +358,12 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
value).
*/
r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
- if(r <= 0)
+ if(r <= 0) {
+ if((r == -1) && (SOCKERRNO == EINTR))
+ /* make EINTR from select or poll not a "lethal" error */
+ r = 0;
return r;
+ }
r = 0;
for(i = 0; i < nfds; i++) {
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index f4bcba30f..f2cf8bbd9 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -34,8 +36,7 @@
* Definition of pollfd struct and constants for platforms lacking them.
*/
-#if !defined(HAVE_STRUCT_POLLFD) && \
- !defined(HAVE_SYS_POLL_H) && \
+#if !defined(HAVE_SYS_POLL_H) && \
!defined(HAVE_POLL_H) && \
!defined(POLLIN)
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index d7d4d8abd..d26b7e7cd 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -46,13 +48,14 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef CURL_DO_LINEEND_CONV
+#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP)
/*
* convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
* (\n), with special processing for CRLF sequences that are split between two
@@ -132,7 +135,7 @@ static size_t convert_lineends(struct Curl_easy *data,
}
return size;
}
-#endif /* CURL_DO_LINEEND_CONV */
+#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
@@ -243,7 +246,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
DEBUGASSERT(!strchr(fmt, '\n'));
if(data && data->set.verbose) {
va_list ap;
- size_t len;
+ int len;
char buffer[MAXINFO + 2];
va_start(ap, fmt);
len = mvsnprintf(buffer, MAXINFO, fmt, ap);
@@ -263,7 +266,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
DEBUGASSERT(!strchr(fmt, '\n'));
if(data->set.verbose || data->set.errorbuffer) {
va_list ap;
- size_t len;
+ int len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
@@ -494,6 +497,9 @@ static CURLcode pausewrite(struct Curl_easy *data,
}
}
DEBUGASSERT(i < 3);
+ if(i >= 3)
+ /* There are more types to store than what fits: very bad */
+ return CURLE_OUT_OF_MEMORY;
}
else
i = 0;
@@ -529,6 +535,7 @@ static CURLcode chop_write(struct Curl_easy *data,
curl_write_callback writebody = NULL;
char *ptr = optr;
size_t len = olen;
+ void *writebody_ptr = data->set.out;
if(!len)
return CURLE_OK;
@@ -539,8 +546,18 @@ static CURLcode chop_write(struct Curl_easy *data,
return pausewrite(data, type, ptr, len);
/* Determine the callback(s) to use. */
- if(type & CLIENTWRITE_BODY)
+ if(type & CLIENTWRITE_BODY) {
+#ifdef USE_WEBSOCKETS
+ if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
+ struct HTTP *ws = data->req.p.http;
+ writebody = Curl_ws_writecb;
+ ws->ws.data = data;
+ writebody_ptr = ws;
+ }
+ else
+#endif
writebody = data->set.fwrite_func;
+ }
if((type & CLIENTWRITE_HEADER) &&
(data->set.fwrite_header || data->set.writeheader)) {
/*
@@ -558,7 +575,7 @@ static CURLcode chop_write(struct Curl_easy *data,
if(writebody) {
size_t wrote;
Curl_set_in_callback(data, true);
- wrote = writebody(ptr, 1, chunklen, data->set.out);
+ wrote = writebody(ptr, 1, chunklen, writebody_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
@@ -581,18 +598,20 @@ static CURLcode chop_write(struct Curl_easy *data,
len -= chunklen;
}
+#ifndef CURL_DISABLE_HTTP
/* HTTP header, but not status-line */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
- CURLcode result =
- Curl_headers_push(data, optr,
- type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
- (type & CLIENTWRITE_1XX ? CURLH_1XX :
- (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
- CURLH_HEADER)));
+ unsigned char htype = (unsigned char)
+ (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
+ (type & CLIENTWRITE_1XX ? CURLH_1XX :
+ (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
+ CURLH_HEADER)));
+ CURLcode result = Curl_headers_push(data, optr, htype);
if(result)
return result;
}
+#endif
if(writeheader) {
size_t wrote;
@@ -605,8 +624,10 @@ static CURLcode chop_write(struct Curl_easy *data,
/* here we pass in the HEADER bit only since if this was body as well
then it was passed already and clearly that didn't trigger the
pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER, optr, olen);
-
+ return pausewrite(data, CLIENTWRITE_HEADER |
+ (type & (CLIENTWRITE_STATUS|CLIENTWRITE_CONNECT|
+ CLIENTWRITE_1XX|CLIENTWRITE_TRAILER)),
+ optr, olen);
if(wrote != olen) {
failf(data, "Failed writing header");
return CURLE_WRITE_ERROR;
@@ -631,22 +652,15 @@ CURLcode Curl_client_write(struct Curl_easy *data,
char *ptr,
size_t len)
{
- struct connectdata *conn = data->conn;
-
- if(!len)
- return CURLE_OK;
-
+#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV)
/* FTP data may need conversion. */
if((type & CLIENTWRITE_BODY) &&
- (conn->handler->protocol & PROTO_FAMILY_FTP) &&
- conn->proto.ftpc.transfertype == 'A') {
-
-#ifdef CURL_DO_LINEEND_CONV
+ (data->conn->handler->protocol & PROTO_FAMILY_FTP) &&
+ data->conn->proto.ftpc.transfertype == 'A') {
/* convert end-of-line markers */
len = convert_lineends(data, ptr, len);
-#endif /* CURL_DO_LINEEND_CONV */
}
-
+#endif
return chop_write(data, type, ptr, len);
}
@@ -714,17 +728,17 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
}
/* return 0 on success */
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size)
+void Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size)
{
- int rc = 0;
if(data->set.verbose) {
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
+ bool inCallback = Curl_is_in_callback(data);
Curl_set_in_callback(data, true);
- rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
- Curl_set_in_callback(data, false);
+ (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, inCallback);
}
else {
switch(type) {
@@ -739,5 +753,4 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
}
}
}
- return rc;
}
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index 6676003a9..7c4c1280a 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -87,8 +89,8 @@ CURLcode Curl_write_plain(struct Curl_easy *data,
ssize_t *written);
/* the function used to output verbose information */
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size);
+void Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size);
#endif /* HEADER_CURL_SENDF_H */
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index 05e1a544d..5b5975485 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -146,6 +148,40 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
#define C_SSLVERSION_VALUE(x) (x & 0xffff)
#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
+static CURLcode protocol2num(const char *str, curl_prot_t *val)
+{
+ if(!str)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(curl_strequal(str, "all")) {
+ *val = ~(curl_prot_t) 0;
+ return CURLE_OK;
+ }
+
+ *val = 0;
+
+ do {
+ const char *token = str;
+ size_t tlen;
+
+ str = strchr(str, ',');
+ tlen = str? (size_t) (str - token): strlen(token);
+ if(tlen) {
+ const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+
+ if(!h)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+
+ *val |= h->protocol;
+ }
+ } while(str++);
+
+ if(!*val)
+ /* no protocol listed */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_OK;
+}
+
/*
* Do not make Curl_vsetopt() static: it is called from
* packages/OS400/ccsidcurl.c.
@@ -155,9 +191,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
char *argptr;
CURLcode result = CURLE_OK;
long arg;
-#ifdef ENABLE_IPV6
unsigned long uarg;
-#endif
curl_off_t bigsize;
switch(option) {
@@ -165,7 +199,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.dns_cache_timeout = arg;
+ else if(arg > INT_MAX)
+ arg = INT_MAX;
+
+ data->set.dns_cache_timeout = (int)arg;
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
/* deprecated */
@@ -203,19 +240,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
case CURLOPT_RANDOM_FILE:
- /*
- * This is the path name to a file that contains random data to seed
- * the random SSL stuff with. The file is only used for reading.
- */
- result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
- va_arg(param, char *));
break;
case CURLOPT_EGDSOCKET:
- /*
- * The Entropy Gathering Daemon socket pathname
- */
- result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
- va_arg(param, char *));
break;
case CURLOPT_MAXCONNECTS:
/*
@@ -318,12 +344,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
/*
- * Option that specifies how quickly an server response must be obtained
+ * Option that specifies how quickly a server response must be obtained
* before it is considered failure. For pingpong protocols.
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.server_response_timeout = arg * 1000;
+ data->set.server_response_timeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
@@ -353,7 +379,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
+ data->set.use_netrc = (unsigned char)arg;
break;
case CURLOPT_NETRC_FILE:
/*
@@ -625,8 +651,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
}
else
data->set.method = HTTPREQ_GET;
+ data->set.upload = FALSE;
break;
+#ifndef CURL_DISABLE_MIME
case CURLOPT_HTTPPOST:
/*
* Set to make us do HTTP POST
@@ -635,6 +663,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+#endif
case CURLOPT_AWS_SIGV4:
/*
@@ -650,18 +679,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
- case CURLOPT_MIMEPOST:
- /*
- * Set to make us do MIME/form POST
- */
- result = Curl_mime_set_subparts(&data->set.mimepost,
- va_arg(param, curl_mime *), FALSE);
- if(!result) {
- data->set.method = HTTPREQ_POST_MIME;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- break;
-
case CURLOPT_REFERER:
/*
* String to set in the HTTP Referer: field.
@@ -683,13 +700,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
va_arg(param, char *));
break;
- case CURLOPT_HTTPHEADER:
- /*
- * Set a list with HTTP headers to use (or replace internals with)
- */
- data->set.headers = va_arg(param, struct curl_slist *);
- break;
-
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYHEADER:
/*
@@ -927,6 +937,36 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif /* CURL_DISABLE_HTTP */
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP)
+# if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+# endif
+
+# ifndef CURL_DISABLE_MIME
+ case CURLOPT_MIMEPOST:
+ /*
+ * Set to make us do MIME POST
+ */
+ result = Curl_mime_set_subparts(&data->set.mimepost,
+ va_arg(param, curl_mime *), FALSE);
+ if(!result) {
+ data->set.method = HTTPREQ_POST_MIME;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_MIME_OPTIONS:
+ data->set.mime_options = (unsigned int)va_arg(param, long);
+ break;
+# endif
+#endif
+
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
@@ -1115,13 +1155,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
break;
-#endif /* CURL_DISABLE_PROXY */
case CURLOPT_SOCKS5_AUTH:
data->set.socks5auth = va_arg(param, unsigned long);
if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
result = CURLE_NOT_BUILT_IN;
break;
+#endif /* CURL_DISABLE_PROXY */
+
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
case CURLOPT_SOCKS5_GSSAPI_NEC:
/*
@@ -1270,7 +1311,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(arg > CURLFTP_CREATE_DIR_RETRY))
result = CURLE_BAD_FUNCTION_ARGUMENT;
else
- data->set.ftp_create_missing_dirs = (int)arg;
+ data->set.ftp_create_missing_dirs = (unsigned char)arg;
break;
case CURLOPT_READDATA:
/*
@@ -1360,12 +1401,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_PORT:
/*
- * The port number to use when getting the URL
+ * The port number to use when getting the URL. 0 disables it.
*/
arg = va_arg(param, long);
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_port = arg;
+ data->set.use_port = (unsigned short)arg;
break;
case CURLOPT_TIMEOUT:
/*
@@ -1374,16 +1415,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.timeout = arg * 1000;
+ data->set.timeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLOPT_TIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.timeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg >= UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.timeout = (unsigned int)uarg;
break;
case CURLOPT_CONNECTTIMEOUT:
@@ -1392,27 +1433,29 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.connecttimeout = arg * 1000;
+ data->set.connecttimeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLOPT_CONNECTTIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.connecttimeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg >= UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.connecttimeout = (unsigned int)uarg;
break;
+#ifndef CURL_DISABLE_FTP
case CURLOPT_ACCEPTTIMEOUT_MS:
/*
- * The maximum time you allow curl to wait for server connect
+ * The maximum time for curl to wait for FTP server connect
*/
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.accepttimeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg >= UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.accepttimeout = (unsigned int)uarg;
break;
+#endif
case CURLOPT_USERPWD:
/*
@@ -1612,13 +1655,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set data write callback
*/
data->set.fwrite_func = va_arg(param, curl_write_callback);
- if(!data->set.fwrite_func) {
- data->set.is_fwrite_set = 0;
+ if(!data->set.fwrite_func)
/* When set to NULL, reset to our internal default function */
data->set.fwrite_func = (curl_write_callback)fwrite;
- }
- else
- data->set.is_fwrite_set = 1;
break;
case CURLOPT_READFUNCTION:
/*
@@ -2166,7 +2205,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else if(arg < READBUFFER_MIN)
arg = READBUFFER_MIN;
- data->set.buffer_size = arg;
+ data->set.buffer_size = (int)arg;
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
@@ -2360,9 +2399,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_CONNECT_ONLY:
/*
- * No data transfer, set up connection and let application use the socket
+ * No data transfer.
+ * (1) - only do connection
+ * (2) - do first get request but get no content
*/
- data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ arg = va_arg(param, long);
+ if(arg > 2)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.connect_only = (unsigned char)arg;
break;
case CURLOPT_SOCKOPTFUNCTION:
@@ -2435,7 +2479,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifdef USE_SSH
/* we only include SSH options if explicitly built to support SSH */
case CURLOPT_SSH_AUTH_TYPES:
- data->set.ssh_auth_types = va_arg(param, long);
+ data->set.ssh_auth_types = (unsigned int)va_arg(param, long);
break;
case CURLOPT_SSH_PUBLIC_KEYFILE:
@@ -2478,7 +2522,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
va_arg(param, char *));
break;
+#ifdef USE_LIBSSH2
+ case CURLOPT_SSH_HOSTKEYFUNCTION:
+ /* the callback to check the hostkey without the knownhost file */
+ data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback);
+ break;
+ case CURLOPT_SSH_HOSTKEYDATA:
+ /*
+ * Custom client data to pass to the SSH keyfunc callback
+ */
+ data->set.ssh_hostkeyfunc_userp = va_arg(param, void *);
+ break;
+#endif
case CURLOPT_SSH_KEYFUNCTION:
/* setting to NULL is fine since the ssh.c functions themselves will
then revert to use the internal default */
@@ -2523,7 +2579,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < 0) || (arg > 0777))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.new_file_perms = arg;
+ data->set.new_file_perms = (unsigned int)arg;
break;
case CURLOPT_NEW_DIRECTORY_PERMS:
@@ -2533,7 +2589,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < 0) || (arg > 0777))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.new_directory_perms = arg;
+ data->set.new_directory_perms = (unsigned int)arg;
break;
#endif
@@ -2558,16 +2614,36 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
- data->set.allowed_protocols = va_arg(param, long);
+ data->set.allowed_protocols = (curl_prot_t)va_arg(param, long);
break;
case CURLOPT_REDIR_PROTOCOLS:
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
- data->set.redir_protocols = va_arg(param, long);
+ data->set.redir_protocols = (curl_prot_t)va_arg(param, long);
break;
+ case CURLOPT_PROTOCOLS_STR: {
+ curl_prot_t prot;
+ argptr = va_arg(param, char *);
+ result = protocol2num(argptr, &prot);
+ if(result)
+ return result;
+ data->set.allowed_protocols = prot;
+ break;
+ }
+
+ case CURLOPT_REDIR_PROTOCOLS_STR: {
+ curl_prot_t prot;
+ argptr = va_arg(param, char *);
+ result = protocol2num(argptr, &prot);
+ if(result)
+ return result;
+ data->set.redir_protocols = prot;
+ break;
+ }
+
case CURLOPT_DEFAULT_PROTOCOL:
/* Set the protocol to use when the URL doesn't include any protocol */
result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
@@ -2596,13 +2672,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
- case CURLOPT_MIME_OPTIONS:
- data->set.mime_options = va_arg(param, long);
- break;
-#endif
-
case CURLOPT_SASL_AUTHZID:
/* Authorization identity (identity to act as) */
result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],
@@ -2833,13 +2902,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if(arg < 0)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.tcp_keepidle = arg;
+ else if(arg > INT_MAX)
+ arg = INT_MAX;
+ data->set.tcp_keepidle = (int)arg;
break;
case CURLOPT_TCP_KEEPINTVL:
arg = va_arg(param, long);
if(arg < 0)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.tcp_keepintvl = arg;
+ else if(arg > INT_MAX)
+ arg = INT_MAX;
+ data->set.tcp_keepintvl = (int)arg;
break;
case CURLOPT_TCP_FASTOPEN:
#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
@@ -2850,7 +2923,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
break;
case CURLOPT_SSL_ENABLE_NPN:
- data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_SSL_ENABLE_ALPN:
data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
@@ -2906,10 +2978,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.happy_eyeballs_timeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg >= UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.happy_eyeballs_timeout = (unsigned int)uarg;
break;
#ifndef CURL_DISABLE_SHUFFLE_DNS
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
@@ -3026,6 +3098,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_PREREQDATA:
data->set.prereq_userp = va_arg(param, void *);
break;
+#ifdef USE_WEBSOCKETS
+ case CURLOPT_WS_OPTIONS: {
+ bool raw;
+ arg = va_arg(param, long);
+ raw = (arg & CURLWS_RAW_MODE);
+ data->set.ws_raw_mode = raw;
+ break;
+ }
+#endif
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
diff --git a/Utilities/cmcurl/lib/setopt.h b/Utilities/cmcurl/lib/setopt.h
index affbfd996..ffc77a71d 100644
--- a/Utilities/cmcurl/lib/setopt.h
+++ b/Utilities/cmcurl/lib/setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
CURLcode Curl_setstropt(char **charp, const char *s);
diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h
index 8c97371e4..6023ca20d 100644
--- a/Utilities/cmcurl/lib/setup-os400.h
+++ b/Utilities/cmcurl/lib/setup-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index a6710d907..b570683d7 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/lib/setup-vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* */
diff --git a/Utilities/cmcurl/lib/setup-win32.h b/Utilities/cmcurl/lib/setup-win32.h
index fa8742f3b..bc5f8efc3 100644
--- a/Utilities/cmcurl/lib/setup-win32.h
+++ b/Utilities/cmcurl/lib/setup-win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -35,10 +37,21 @@
#ifdef HAVE_WINDOWS_H
# if defined(UNICODE) && !defined(_UNICODE)
-# define _UNICODE
+# error "UNICODE is defined but _UNICODE is not defined"
# endif
# if defined(_UNICODE) && !defined(UNICODE)
-# define UNICODE
+# error "_UNICODE is defined but UNICODE is not defined"
+# endif
+/*
+ * Don't include unneeded stuff in Windows headers to avoid compiler
+ * warnings and macro clashes.
+ * Make sure to define this macro before including any Windows headers.
+ */
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOGDI
+# define NOGDI
# endif
# include <winerror.h>
# include <windows.h>
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index 1e879f60f..60720f5b1 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/share.c b/Utilities/cmcurl/lib/share.c
index 403563fdd..1a083e72a 100644
--- a/Utilities/cmcurl/lib/share.c
+++ b/Utilities/cmcurl/lib/share.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -39,7 +41,7 @@ curl_share_init(void)
if(share) {
share->magic = CURL_GOOD_SHARE;
share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
- Curl_init_dnscache(&share->hostcache);
+ Curl_init_dnscache(&share->hostcache, 23);
}
return share;
diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index 222e34ba6..32be41691 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/sigpipe.h b/Utilities/cmcurl/lib/sigpipe.h
index d6ec5fca3..d12b31764 100644
--- a/Utilities/cmcurl/lib/sigpipe.h
+++ b/Utilities/cmcurl/lib/sigpipe.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/slist.c b/Utilities/cmcurl/lib/slist.c
index 907c203f3..6c80722c7 100644
--- a/Utilities/cmcurl/lib/slist.c
+++ b/Utilities/cmcurl/lib/slist.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/slist.h b/Utilities/cmcurl/lib/slist.h
index 3114259cf..4e5834c90 100644
--- a/Utilities/cmcurl/lib/slist.h
+++ b/Utilities/cmcurl/lib/slist.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 8f44704a2..a62e85814 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -32,7 +34,7 @@
#include <process.h>
#ifdef CURL_WINDOWS_APP
#define getpid GetCurrentProcessId
-#elif !defined(MSDOS)
+#elif defined(WIN32)
#define getpid _getpid
#endif
#endif
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index 0e3c2ec11..919f3ac14 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
+ * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
enum smb_conn_state {
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index c736cfae1..6ebb41af6 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC1870 SMTP Service Extension for Message Size
* RFC2195 CRAM-MD5 authentication
* RFC2831 DIGEST-MD5 authentication
@@ -1818,7 +1820,9 @@ static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
return result;
}
-CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data,
+ const ssize_t nread,
+ const ssize_t offset)
{
/* When sending a SMTP payload we must detect CRLF. sequences making sure
they are sent as CRLF.. instead, as a . on the beginning of a line will
@@ -1852,7 +1856,9 @@ CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
/* This loop can be improved by some kind of Boyer-Moore style of
approach but that is saved for later... */
- for(i = 0, si = 0; i < nread; i++) {
+ if(offset)
+ memcpy(scratch, data->req.upload_fromhere, offset);
+ for(i = offset, si = offset; i < nread; i++) {
if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
smtp->eob++;
diff --git a/Utilities/cmcurl/lib/smtp.h b/Utilities/cmcurl/lib/smtp.h
index 1fe45346e..24c5589e4 100644
--- a/Utilities/cmcurl/lib/smtp.h
+++ b/Utilities/cmcurl/lib/smtp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "pingpong.h"
@@ -91,6 +93,8 @@ extern const struct Curl_handler Curl_handler_smtps;
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4
-CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread);
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data,
+ const ssize_t nread,
+ const ssize_t offset);
#endif /* HEADER_CURL_SMTP_H */
diff --git a/Utilities/cmcurl/lib/sockaddr.h b/Utilities/cmcurl/lib/sockaddr.h
index 84c08d9bb..77ec833ee 100644
--- a/Utilities/cmcurl/lib/sockaddr.h
+++ b/Utilities/cmcurl/lib/sockaddr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/socketpair.c b/Utilities/cmcurl/lib/socketpair.c
index 409d2ad66..0f8798f08 100644
--- a/Utilities/cmcurl/lib/socketpair.c
+++ b/Utilities/cmcurl/lib/socketpair.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/socketpair.h b/Utilities/cmcurl/lib/socketpair.h
index cdcc0b921..de70df673 100644
--- a/Utilities/cmcurl/lib/socketpair.h
+++ b/Utilities/cmcurl/lib/socketpair.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,10 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifndef HAVE_SOCKETPAIR
+#include <curl/curl.h>
+
int Curl_socketpair(int domain, int type, int protocol,
curl_socket_t socks[2]);
#else
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index d614ae59c..52c29880a 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index f30c610a8..ff83aa561 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/lib/socks.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 8ef2f8f37..f14099feb 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -51,7 +53,7 @@ static int check_gss_err(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
OM_uint32 maj_stat, min_stat;
OM_uint32 msg_ctx = 0;
- gss_buffer_desc status_string;
+ gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
char buf[1024];
size_t len;
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index ffc870346..210a0dfbc 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012, 2011, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index 841d256b4..3ddc43d2d 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/speedcheck.h b/Utilities/cmcurl/lib/speedcheck.h
index 1d4c7bfef..cb44eb04e 100644
--- a/Utilities/cmcurl/lib/speedcheck.h
+++ b/Utilities/cmcurl/lib/speedcheck.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index bcc079521..33b44aa1c 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -101,7 +103,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
struct Curl_tree *node)
{
static const struct curltime KEY_NOTUSED = {
- (time_t)-1, (unsigned int)-1
+ ~0, -1
}; /* will *NEVER* appear */
if(!node)
@@ -211,7 +213,7 @@ int Curl_splayremove(struct Curl_tree *t,
struct Curl_tree **newroot)
{
static const struct curltime KEY_NOTUSED = {
- (time_t)-1, (unsigned int)-1
+ ~0, -1
}; /* will *NEVER* appear */
struct Curl_tree *x;
diff --git a/Utilities/cmcurl/lib/splay.h b/Utilities/cmcurl/lib/splay.h
index eb9f65f1e..015e2ca52 100644
--- a/Utilities/cmcurl/lib/splay.h
+++ b/Utilities/cmcurl/lib/splay.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#include "timeval.h"
diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c
index 692a3f14a..09d2a8a96 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -26,25 +28,58 @@
#include "strcase.h"
-static char raw_tolower(char in);
+/* Mapping table to go from lowercase to uppercase for plain ASCII.*/
+static const unsigned char touppermap[256] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65,
+66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+};
+
+/* Mapping table to go from uppercase to lowercase for plain ASCII.*/
+static const unsigned char tolowermap[256] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95,
+96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+};
+
/* Portable, consistent toupper. Do not use toupper() because its behavior is
altered by the current locale. */
char Curl_raw_toupper(char in)
{
- if(in >= 'a' && in <= 'z')
- return (char)('A' + in - 'a');
- return in;
+ return touppermap[(unsigned char) in];
}
/* Portable, consistent tolower. Do not use tolower() because its behavior is
altered by the current locale. */
-static char raw_tolower(char in)
+char Curl_raw_tolower(char in)
{
- if(in >= 'A' && in <= 'Z')
- return (char)('a' + in - 'A');
- return in;
+ return tolowermap[(unsigned char) in];
}
/*
@@ -62,14 +97,15 @@ int Curl_strcasecompare(const char *first, const char *second)
while(*first && *second) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
/* get out of the loop as soon as they don't match */
- break;
+ return 0;
first++;
second++;
}
- /* we do the comparison here (possibly again), just to make sure that if the
- loop above is skipped because one of the strings reached zero, we must not
- return this as a successful match */
- return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
+ /* If we're here either the strings are the same or the length is different.
+ We can just test if the "current" character is non-zero for one and zero
+ for the other. Note that the characters may not be exactly the same even
+ if they match, we only want to compare zero-ness. */
+ return !*first == !*second;
}
int Curl_safe_strcasecompare(const char *first, const char *second)
@@ -127,7 +163,7 @@ void Curl_strntolower(char *dest, const char *src, size_t n)
return;
do {
- *dest++ = raw_tolower(*src);
+ *dest++ = Curl_raw_tolower(*src);
} while(*src++ && --n);
}
@@ -141,6 +177,28 @@ bool Curl_safecmp(char *a, char *b)
return !a && !b;
}
+/*
+ * Curl_timestrcmp() returns 0 if the two strings are identical. The time this
+ * function spends is a function of the shortest string, not of the contents.
+ */
+int Curl_timestrcmp(const char *a, const char *b)
+{
+ int match = 0;
+ int i = 0;
+
+ if(a && b) {
+ while(1) {
+ match |= a[i]^b[i];
+ if(!a[i] || !b[i])
+ break;
+ i++;
+ }
+ }
+ else
+ return a || b;
+ return match;
+}
+
/* --- public functions --- */
int curl_strequal(const char *first, const char *second)
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index 2635f5117..65a575385 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
@@ -41,6 +43,7 @@ int Curl_safe_strcasecompare(const char *first, const char *second);
int Curl_strncasecompare(const char *first, const char *second, size_t max);
char Curl_raw_toupper(char in);
+char Curl_raw_tolower(char in);
/* checkprefix() is a shorter version of the above, used when the first
argument is the string literal */
@@ -50,5 +53,6 @@ void Curl_strntoupper(char *dest, const char *src, size_t n);
void Curl_strntolower(char *dest, const char *src, size_t n);
bool Curl_safecmp(char *a, char *b);
+int Curl_timestrcmp(const char *first, const char *second);
#endif /* HEADER_CURL_STRCASE_H */
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 85cf33b3e..ac22b6dda 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index 8c8a6f20e..fb46808b8 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 781e26b69..b9a51e26b 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -263,9 +265,6 @@ curl_easy_strerror(CURLcode error)
case CURLE_TFTP_NOSUCHUSER:
return "TFTP: No such user";
- case CURLE_CONV_FAILED:
- return "Conversion failed";
-
case CURLE_REMOTE_FILE_NOT_FOUND:
return "Remote file not found";
@@ -317,6 +316,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_SSL_CLIENTCERT:
return "SSL Client Certificate required";
+ case CURLE_UNRECOVERABLE_POLL:
+ return "Unrecoverable error in select/poll";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -329,6 +331,7 @@ curl_easy_strerror(CURLcode error)
case CURLE_OBSOLETE51:
case CURLE_OBSOLETE57:
case CURLE_OBSOLETE62:
+ case CURLE_OBSOLETE75:
case CURLE_OBSOLETE76:
case CURL_LAST:
break;
@@ -400,6 +403,9 @@ curl_multi_strerror(CURLMcode error)
case CURLM_ABORTED_BY_CALLBACK:
return "Operation was aborted by an application callback";
+ case CURLM_UNRECOVERABLE_POLL:
+ return "Unrecoverable error in select/poll";
+
case CURLM_LAST:
break;
}
@@ -470,7 +476,7 @@ curl_url_strerror(CURLUcode error)
return "Port number was not a decimal number between 0 and 65535";
case CURLUE_UNSUPPORTED_SCHEME:
- return "This libcurl build doesn't support the given URL scheme";
+ return "Unsupported URL scheme";
case CURLUE_URLDECODE:
return "URL decode error, most likely because of rubbish in the input";
@@ -524,7 +530,7 @@ curl_url_strerror(CURLUcode error)
return "Bad file:// URL";
case CURLUE_BAD_SLASHES:
- return "Unsupported number of slashes";
+ return "Unsupported number of slashes following scheme";
case CURLUE_BAD_SCHEME:
return "Bad scheme";
diff --git a/Utilities/cmcurl/lib/strerror.h b/Utilities/cmcurl/lib/strerror.h
index 96a7e27c5..658f16c10 100644
--- a/Utilities/cmcurl/lib/strerror.h
+++ b/Utilities/cmcurl/lib/strerror.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "urldata.h"
diff --git a/Utilities/cmcurl/lib/strtok.c b/Utilities/cmcurl/lib/strtok.c
index d53e587ab..6120bcc28 100644
--- a/Utilities/cmcurl/lib/strtok.c
+++ b/Utilities/cmcurl/lib/strtok.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/strtok.h b/Utilities/cmcurl/lib/strtok.h
index 831ef0c00..641a3daed 100644
--- a/Utilities/cmcurl/lib/strtok.h
+++ b/Utilities/cmcurl/lib/strtok.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#include <stddef.h>
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index ac87cfc5b..30deb8c05 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <errno.h>
@@ -85,7 +87,7 @@ static curl_off_t strtooff(const char *nptr, char **endptr, int base)
/* Skip leading whitespace. */
end = (char *)nptr;
- while(ISSPACE(end[0])) {
+ while(ISBLANK(end[0])) {
end++;
}
@@ -220,9 +222,9 @@ CURLofft curlx_strtoofft(const char *str, char **endp, int base,
errno = 0;
*num = 0; /* clear by default */
- while(*str && ISSPACE(*str))
+ while(*str && ISBLANK(*str))
str++;
- if('-' == *str) {
+ if(('-' == *str) || (ISSPACE(*str))) {
if(endp)
*endp = (char *)str; /* didn't actually move */
return CURL_OFFT_INVAL; /* nothing parsed */
diff --git a/Utilities/cmcurl/lib/strtoofft.h b/Utilities/cmcurl/lib/strtoofft.h
index 4d22ba36c..311dae440 100644
--- a/Utilities/cmcurl/lib/strtoofft.h
+++ b/Utilities/cmcurl/lib/strtoofft.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index 9a6dd9cef..bede9c7dc 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2021, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/system_win32.h b/Utilities/cmcurl/lib/system_win32.h
index 69e0c812c..167804e3c 100644
--- a/Utilities/cmcurl/lib/system_win32.h
+++ b/Utilities/cmcurl/lib/system_win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index 2abfcd952..923c7f82b 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/telnet.h b/Utilities/cmcurl/lib/telnet.h
index 1427473a9..6dd99b48d 100644
--- a/Utilities/cmcurl/lib/telnet.h
+++ b/Utilities/cmcurl/lib/telnet.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_TELNET
extern const struct Curl_handler Curl_handler_telnet;
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 7f2c88b71..9e6d9490e 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/tftp.h b/Utilities/cmcurl/lib/tftp.h
index 4b5bea275..3f1fda638 100644
--- a/Utilities/cmcurl/lib/tftp.h
+++ b/Utilities/cmcurl/lib/tftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef CURL_DISABLE_TFTP
extern const struct Curl_handler Curl_handler_tftp;
diff --git a/Utilities/cmcurl/lib/timediff.c b/Utilities/cmcurl/lib/timediff.c
index 003477c63..c5893187d 100644
--- a/Utilities/cmcurl/lib/timediff.c
+++ b/Utilities/cmcurl/lib/timediff.c
@@ -18,10 +18,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "timediff.h"
+#include <limits.h>
+
/*
* Converts number of milliseconds into a timeval structure.
*
diff --git a/Utilities/cmcurl/lib/timediff.h b/Utilities/cmcurl/lib/timediff.h
index fcd5f0563..90e547457 100644
--- a/Utilities/cmcurl/lib/timediff.h
+++ b/Utilities/cmcurl/lib/timediff.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index ca98fe50e..647d7b0fc 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "timeval.h"
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index dce32f4cd..8d4fef4e1 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 315da876c..441da7342 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -202,6 +204,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
}
#endif
+#ifndef CURL_DISABLE_HTTP
/* if we are transmitting trailing data, we don't need to write
a chunk size so we skip this */
if(data->req.upload_chunky &&
@@ -211,7 +214,6 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
}
-#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_SENDING) {
/* if we're here then that means that we already sent the last empty chunk
but we didn't send a final CR LF, so we sent 0 CR LF. We then start
@@ -267,6 +269,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
return CURLE_READ_ERROR;
}
+#ifndef CURL_DISABLE_HTTP
if(!data->req.forbidchunk && data->req.upload_chunky) {
/* if chunked Transfer-Encoding
* build chunk:
@@ -317,15 +320,12 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
/* always append ASCII CRLF to the data unless
we have a valid trailer callback */
-#ifndef CURL_DISABLE_HTTP
if((nread-hexlen) == 0 &&
data->set.trailer_callback != NULL &&
data->state.trailers_state == TRAILERS_NONE) {
data->state.trailers_state = TRAILERS_INITIALIZED;
}
- else
-#endif
- {
+ else {
memcpy(data->req.upload_fromhere + nread,
endofline_network,
strlen(endofline_network));
@@ -333,7 +333,6 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
}
}
-#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_SENDING &&
!trailers_left(data)) {
Curl_dyn_free(&data->state.trailers_buf);
@@ -345,7 +344,6 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
infof(data, "Signaling end of chunked upload after trailers.");
}
else
-#endif
if((nread - hexlen) == 0 &&
data->state.trailers_state != TRAILERS_INITIALIZED) {
/* mark this as done once this chunk is transferred */
@@ -357,6 +355,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
if(added_crlf)
nread += strlen(endofline_network); /* for the added end of line */
}
+#endif
*nreadp = nread;
@@ -540,6 +539,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
bool is_http2 = ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(conn->httpversion == 20));
#endif
+ bool is_http3 =
+#ifdef ENABLE_QUIC
+ ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (conn->httpversion == 30));
+#else
+ FALSE;
+#endif
if(
#ifdef USE_NGHTTP2
@@ -550,6 +556,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
for a particular stream. */
!is_http2 &&
#endif
+ !is_http3 && /* Same reason mentioned above. */
k->size != -1 && !k->header) {
/* make sure we don't read too much */
curl_off_t totalleft = k->size - k->bytecount;
@@ -597,6 +604,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
else
#endif
+ if(is_http3 && !nread)
+ DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
+ else
DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
k->keepon &= ~KEEP_RECV;
break;
@@ -754,7 +764,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(nread < 0) /* this should be unusual */
nread = 0;
- k->keepon &= ~KEEP_RECV; /* we're done reading */
+ /* HTTP/3 over QUIC should keep reading until QUIC connection
+ is closed. In contrast to HTTP/2 which can stop reading
+ from TCP connection, HTTP/3 over QUIC needs ACK from server
+ to ensure stream closure. It should keep reading. */
+ if(!is_http3) {
+ k->keepon &= ~KEEP_RECV; /* we're done reading */
+ }
}
k->bytecount += nread;
@@ -900,6 +916,9 @@ static void win_update_buffer_size(curl_socket_t sockfd)
#define win_update_buffer_size(x)
#endif
+#define curl_upload_refill_watermark(data) \
+ ((ssize_t)((data)->set.upload_buffer_size >> 5))
+
/*
* Send data to upload to the server, when the socket is writable.
*/
@@ -921,13 +940,25 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
do {
curl_off_t nbody;
+ ssize_t offset = 0;
+
+ if(0 != k->upload_present &&
+ k->upload_present < curl_upload_refill_watermark(data) &&
+ !k->upload_chunky &&/*(variable sized chunked header; append not safe)*/
+ !k->upload_done && /*!(k->upload_done once k->upload_present sent)*/
+ !(k->writebytecount + k->upload_present - k->pendingheader ==
+ data->state.infilesize)) {
+ offset = k->upload_present;
+ }
/* only read more data if there's no upload data already
- present in the upload buffer */
- if(0 == k->upload_present) {
+ present in the upload buffer, or if appending to upload buffer */
+ if(0 == k->upload_present || offset) {
result = Curl_get_upload_buffer(data);
if(result)
return result;
+ if(offset && k->upload_fromhere != data->state.ulbuf)
+ memmove(data->state.ulbuf, k->upload_fromhere, offset);
/* init the "upload from here" pointer */
k->upload_fromhere = data->state.ulbuf;
@@ -960,12 +991,14 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
+ k->upload_fromhere += offset;
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size-offset,
&fillcount);
+ k->upload_fromhere -= offset;
if(result)
return result;
- nread = fillcount;
+ nread = offset + fillcount;
}
else
nread = 0; /* we're done uploading/reading */
@@ -1007,7 +1040,9 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
* That means the hex values for ASCII CR (0x0d) & LF (0x0a)
* must be used instead of the escape sequences \r & \n.
*/
- for(i = 0, si = 0; i < nread; i++, si++) {
+ if(offset)
+ memcpy(data->state.scratch, k->upload_fromhere, offset);
+ for(i = offset, si = offset; i < nread; i++, si++) {
if(k->upload_fromhere[i] == 0x0a) {
data->state.scratch[si++] = 0x0d;
data->state.scratch[si] = 0x0a;
@@ -1037,12 +1072,12 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
#ifndef CURL_DISABLE_SMTP
if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
- result = Curl_smtp_escape_eob(data, nread);
+ result = Curl_smtp_escape_eob(data, nread, offset);
if(result)
return result;
}
#endif /* CURL_DISABLE_SMTP */
- } /* if 0 == k->upload_present */
+ } /* if 0 == k->upload_present or appended to upload buffer */
else {
/* We have a partial buffer left from a previous "round". Use
that instead of reading more data */
@@ -1153,10 +1188,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
else
fd_write = CURL_SOCKET_BAD;
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
if(data->state.drain) {
select_res |= CURL_CSELECT_IN;
DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data"));
}
+#endif
if(!select_res) /* Call for select()/poll() only, if read/write/error
status is not known. */
@@ -1222,6 +1259,14 @@ CURLcode Curl_readwrite(struct connectdata *conn,
infof(data, "Done waiting for 100-continue");
}
}
+
+#ifdef ENABLE_QUIC
+ if(conn->transport == TRNSPRT_QUIC) {
+ result = Curl_quic_idle(data);
+ if(result)
+ return result;
+ }
+#endif
}
if(Curl_pgrsUpdate(data))
@@ -1394,7 +1439,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
if(result)
return result;
- data->state.wildcardmatch = data->set.wildcard_enabled;
+ data->state.requests = 0;
data->state.followlocation = 0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
@@ -1416,10 +1461,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
else
data->state.infilesize = 0;
+#ifndef CURL_DISABLE_COOKIES
/* If there is a list of cookie files to read, do it now! */
if(data->state.cookielist)
Curl_cookie_loadfiles(data);
-
+#endif
/* If there is a list of host pairs to deal with */
if(data->state.resolve)
result = Curl_loadhostpairs(data);
@@ -1449,6 +1495,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
data->state.authproxy.picked &= data->state.authproxy.want;
#ifndef CURL_DISABLE_FTP
+ data->state.wildcardmatch = data->set.wildcard_enabled;
if(data->state.wildcardmatch) {
struct WildcardData *wc = &data->wildcard;
if(wc->state < CURLWC_INIT) {
@@ -1562,7 +1609,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->state.referer_alloc = FALSE;
}
- /* Make a copy of the URL without crenditals and fragment */
+ /* Make a copy of the URL without credentials and fragment */
u = curl_url();
if(!u)
return CURLE_OUT_OF_MEMORY;
@@ -1590,7 +1637,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
if((type != FOLLOW_RETRY) &&
(data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0))
+ Curl_is_absolute_url(newurl, NULL, 0, FALSE))
/* If this is not redirect due to a 401 or 407 response and an absolute
URL: don't allow a custom port number */
disallowport = TRUE;
@@ -1599,10 +1646,14 @@ CURLcode Curl_follow(struct Curl_easy *data,
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
(type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
- CURLU_ALLOW_SPACE);
+ CURLU_ALLOW_SPACE |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- if(type != FOLLOW_FAKE)
+ if(type != FOLLOW_FAKE) {
+ failf(data, "The redirect target URL could not be parsed: %s",
+ curl_url_strerror(uc));
return Curl_uc_to_curlcode(uc);
+ }
/* the URL could not be parsed for some reason, but since this is FAKE
mode, just duplicate the field as-is */
@@ -1649,7 +1700,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- p = Curl_builtin_scheme(scheme);
+ p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(p && (p->protocol != data->info.conn_protocol)) {
infof(data, "Clear auth, redirects scheme from %s to %s",
data->info.conn_scheme, scheme);
@@ -1813,10 +1864,12 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
return CURLE_OK;
if((data->req.bytecount + data->req.headerbytecount == 0) &&
- conn->bits.reuse &&
- (!data->set.opt_no_body
- || (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
- (data->set.rtspreq != RTSPREQ_RECEIVE))
+ conn->bits.reuse &&
+ (!data->set.opt_no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
+#ifndef CURL_DISABLE_RTSP
+ && (data->set.rtspreq != RTSPREQ_RECEIVE)
+#endif
+ )
/* We got no data, we attempted to re-use a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
@@ -1888,11 +1941,14 @@ Curl_setup_transfer(
struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
struct HTTP *http = data->req.p.http;
- bool httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
- (http->sending == HTTPSEND_REQUEST));
+ bool httpsending;
+
DEBUGASSERT(conn != NULL);
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+ httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ (http->sending == HTTPSEND_REQUEST));
+
if(conn->bits.multiplex || conn->httpversion == 20 || httpsending) {
/* when multiplexing, the read/write sockets need to be the same! */
conn->sockfd = sockindex == -1 ?
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 56d2fd1ee..65fe68e81 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 6b31d4b13..be5ffca2d 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -71,10 +73,11 @@
#endif
#elif defined(USE_WIN32_IDN)
-/* prototype for curl_win32_idn_to_ascii() */
-bool curl_win32_idn_to_ascii(const char *in, char **out);
+/* prototype for Curl_win32_idn_to_ascii() */
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_LIBIDN2 */
+#include "doh.h"
#include "urldata.h"
#include "netrc.h"
@@ -103,6 +106,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "urlapi-int.h"
#include "system_win32.h"
#include "hsts.h"
+#include "noproxy.h"
/* And now for the protocols */
#include "ftp.h"
@@ -125,7 +129,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "http_proxy.h"
#include "conncache.h"
#include "multihandle.h"
-#include "dotdot.h"
#include "strdup.h"
#include "setopt.h"
#include "altsvc.h"
@@ -147,6 +150,13 @@ static void conn_free(struct connectdata *conn);
# error READBUFFER_SIZE is too small
#endif
+#ifdef USE_UNIX_SOCKETS
+#define UNIX_SOCKET_PREFIX "localhost"
+#endif
+
+/* Reject URLs exceeding this length */
+#define MAX_URL_LEN 0xffff
+
/*
* get_protocol_family()
*
@@ -158,7 +168,7 @@ static void conn_free(struct connectdata *conn);
*
* Returns the family as a single bit protocol identifier.
*/
-static unsigned int get_protocol_family(const struct Curl_handler *h)
+static curl_prot_t get_protocol_family(const struct Curl_handler *h)
{
DEBUGASSERT(h);
DEBUGASSERT(h->family);
@@ -182,6 +192,16 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_http,
#endif
+#ifdef USE_WEBSOCKETS
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_ws,
+#endif
+#endif
+
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
@@ -433,6 +453,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.wouldredirect);
/* this destroys the channel and we cannot use it anymore after this */
+ Curl_resolver_cancel(data);
Curl_resolver_cleanup(data->state.async.resolver);
Curl_http2_cleanup_dependencies(data);
@@ -495,7 +516,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
/* use fread as default function to read input */
set->fread_func_set = (curl_read_callback)fread;
set->is_fread_set = 0;
- set->is_fwrite_set = 0;
set->seek_func = ZERO_NULL;
set->seek_client = ZERO_NULL;
@@ -505,7 +525,9 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->maxredirs = -1; /* allow any amount by default */
set->method = HTTPREQ_GET; /* Default HTTP request */
+#ifndef CURL_DISABLE_RTSP
set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
+#endif
#ifndef CURL_DISABLE_FTP
set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
@@ -521,10 +543,12 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->proxyport = 0;
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
- set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
+#ifndef CURL_DISABLE_PROXY
+ set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
/* SOCKS5 proxy auth defaults to username/password + GSS-API */
set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
+#endif
/* make libcurl quiet by default: */
set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
@@ -544,8 +568,8 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
#ifdef USE_TLS_SRP
set->ssl.primary.authtype = CURL_TLSAUTH_NONE;
#endif
- set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
- type */
+ /* defaults to any auth type */
+ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
default */
#ifndef CURL_DISABLE_PROXY
@@ -554,11 +578,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
-
- /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
- define since we internally only use the lower 16 bits for the passed
- in bitmask to not conflict with the private bits */
- set->allowed_protocols = CURLPROTO_ALL;
+ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
CURLPROTO_FTPS;
@@ -598,22 +618,23 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
#endif
}
+#ifndef CURL_DISABLE_FTP
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
set->chunk_end = ZERO_NULL;
+ set->fnmatch = ZERO_NULL;
+#endif
set->tcp_keepalive = FALSE;
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
- set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
- set->fnmatch = ZERO_NULL;
set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
set->maxage_conn = 118;
@@ -730,15 +751,6 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
DEBUGASSERT(data);
infof(data, "Closing connection %ld", conn->connection_id);
-#ifndef USE_HYPER
- if(conn->connect_state && conn->connect_state->prot_save) {
- /* If this was closed with a CONNECT in progress, cleanup this temporary
- struct arrangement */
- data->req.p.http = NULL;
- Curl_safefree(conn->connect_state->prot_save);
- }
-#endif
-
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
@@ -853,7 +865,7 @@ void Curl_disconnect(struct Curl_easy *data,
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- if(conn->bits.connect_only)
+ if(conn->connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
@@ -937,19 +949,11 @@ socks_proxy_info_matches(const struct proxy_info *data,
/* the user information is case-sensitive
or at least it is not defined as case-insensitive
see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */
- if(!data->user != !needle->user)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->user &&
- needle->user &&
- strcmp(data->user, needle->user) != 0)
- return FALSE;
- if(!data->passwd != !needle->passwd)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->passwd &&
- needle->passwd &&
- strcmp(data->passwd, needle->passwd) != 0)
+
+ /* curl_strequal does a case insensitive comparison,
+ so do not use it here! */
+ if(Curl_timestrcmp(data->user, needle->user) ||
+ Curl_timestrcmp(data->passwd, needle->passwd))
return FALSE;
return TRUE;
}
@@ -1100,12 +1104,17 @@ static void prune_dead_connections(struct Curl_easy *data)
}
}
+#ifdef USE_SSH
static bool ssh_config_matches(struct connectdata *one,
struct connectdata *two)
{
return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub));
}
+#else
+#define ssh_config_matches(x,y) FALSE
+#endif
+
/*
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
@@ -1194,7 +1203,7 @@ ConnectionExists(struct Curl_easy *data,
check = curr->ptr;
curr = curr->next;
- if(check->bits.connect_only || check->bits.close)
+ if(check->connect_only || check->bits.close)
/* connect-only or to-be-closed connections will not be reused */
continue;
@@ -1346,10 +1355,10 @@ ConnectionExists(struct Curl_easy *data,
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd) ||
- !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
- !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
/* one of them was different */
continue;
}
@@ -1425,8 +1434,8 @@ ConnectionExists(struct Curl_easy *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
/* we prefer a credential match, but this is at least a connection
that can be reused and "upgraded" to NTLM */
@@ -1448,8 +1457,10 @@ ConnectionExists(struct Curl_easy *data,
if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
- strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
continue;
}
else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
@@ -1621,7 +1632,7 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
#elif defined(USE_WIN32_IDN)
char *ace_hostname = NULL;
- if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
+ if(Curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
host->encalloc = ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
@@ -1652,7 +1663,7 @@ void Curl_free_idnconverted_hostname(struct hostname *host)
}
#elif defined(USE_WIN32_IDN)
free(host->encalloc); /* must be freed with free() since this was
- allocated by curl_win32_idn_to_ascii */
+ allocated by Curl_win32_idn_to_ascii */
host->encalloc = NULL;
#else
(void)host;
@@ -1770,19 +1781,15 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
-#ifdef USE_TLS_SRP
-#endif
#ifndef CURL_DISABLE_PROXY
conn->proxy_ssl_config.verifystatus =
data->set.proxy_ssl.primary.verifystatus;
conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
-#ifdef USE_TLS_SRP
-#endif
#endif
conn->ip_version = data->set.ipver;
- conn->bits.connect_only = data->set.connect_only;
+ conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
@@ -1826,15 +1833,18 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
}
/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
/* Scan protocol handler table and match against 'scheme'. The handler may
be changed later when the protocol specific setup function is called. */
+ if(schemelen == CURL_ZERO_TERMINATED)
+ schemelen = strlen(scheme);
for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strcasecompare(p->scheme, scheme))
- /* Protocol found in table. Check if allowed */
+ if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
+ /* Protocol found in table. */
return p;
return NULL; /* not found */
}
@@ -1844,7 +1854,8 @@ static CURLcode findprotocol(struct Curl_easy *data,
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr);
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr,
+ CURL_ZERO_TERMINATED);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1968,7 +1979,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
- !Curl_is_absolute_url(data->state.url, NULL, 0)) {
+ !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
data->state.url);
if(!url)
@@ -2012,10 +2023,60 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
}
+ else if(strlen(data->state.up.hostname) > MAX_URL_LEN) {
+ failf(data, "Too long host name (maximum is %d)", MAX_URL_LEN);
+ return CURLE_URL_MALFORMAT;
+ }
+ hostname = data->state.up.hostname;
+
+ if(hostname && hostname[0] == '[') {
+ /* This looks like an IPv6 address literal. See if there is an address
+ scope. */
+ size_t hlen;
+ conn->bits.ipv6_ip = TRUE;
+ /* cut off the brackets! */
+ hostname++;
+ hlen = strlen(hostname);
+ hostname[hlen - 1] = 0;
+
+ zonefrom_url(uh, data, conn);
+ }
+
+ /* make sure the connect struct gets its own copy of the host name */
+ conn->host.rawalloc = strdup(hostname ? hostname : "");
+ if(!conn->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ conn->host.name = conn->host.rawalloc;
+
+ /*************************************************************
+ * IDN-convert the hostnames
+ *************************************************************/
+ result = Curl_idnconvert_hostname(data, &conn->host);
+ if(result)
+ return result;
+ if(conn->bits.conn_to_host) {
+ result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
+ if(result)
+ return result;
+ }
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy) {
+ result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
+ if(result)
+ return result;
+ }
+ if(conn->bits.socksproxy) {
+ result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
+ if(result)
+ return result;
+ }
+#endif
#ifndef CURL_DISABLE_HSTS
+ /* HSTS upgrade */
if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
- if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
+ /* This MUST use the IDN decoded name */
+ if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
char *url;
Curl_safefree(data->state.up.scheme);
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
@@ -2066,7 +2127,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- if(!data->state.aptr.user) {
+ if(!data->set.str[STRING_USERNAME]) {
/* we don't use the URL API's URL decoder option here since it rejects
control codes and we want to allow them for some schemes in the user
and password fields */
@@ -2101,7 +2162,8 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
else if(uc != CURLUE_NO_OPTIONS)
return Curl_uc_to_curlcode(uc);
- uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
+ uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path,
+ CURLU_URLENCODE);
if(uc)
return Curl_uc_to_curlcode(uc);
@@ -2115,31 +2177,11 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
unsigned long port = strtoul(data->state.up.port, NULL, 10);
conn->port = conn->remote_port =
(data->set.use_port && data->state.allow_port) ?
- (int)data->set.use_port : curlx_ultous(port);
+ data->set.use_port : curlx_ultous(port);
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
- hostname = data->state.up.hostname;
- if(hostname && hostname[0] == '[') {
- /* This looks like an IPv6 address literal. See if there is an address
- scope. */
- size_t hlen;
- conn->bits.ipv6_ip = TRUE;
- /* cut off the brackets! */
- hostname++;
- hlen = strlen(hostname);
- hostname[hlen - 1] = 0;
-
- zonefrom_url(uh, data, conn);
- }
-
- /* make sure the connect struct gets its own copy of the host name */
- conn->host.rawalloc = strdup(hostname ? hostname : "");
- if(!conn->host.rawalloc)
- return CURLE_OUT_OF_MEMORY;
- conn->host.name = conn->host.rawalloc;
-
#ifdef ENABLE_IPV6
if(data->set.scope_id)
/* Override any scope that was set above. */
@@ -2237,83 +2279,6 @@ void Curl_free_request_state(struct Curl_easy *data)
#ifndef CURL_DISABLE_PROXY
-/****************************************************************
-* Checks if the host is in the noproxy list. returns true if it matches
-* and therefore the proxy should NOT be used.
-****************************************************************/
-static bool check_noproxy(const char *name, const char *no_proxy)
-{
- /* no_proxy=domain1.dom,host.domain2.dom
- * (a comma-separated list of hosts which should
- * not be proxied, or an asterisk to override
- * all proxy variables)
- */
- if(no_proxy && no_proxy[0]) {
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
- if(strcasecompare("*", no_proxy)) {
- return TRUE;
- }
-
- /* NO_PROXY was specified and it wasn't just an asterisk */
-
- no_proxy_len = strlen(no_proxy);
- if(name[0] == '[') {
- /* IPv6 numerical address */
- endptr = strchr(name, ']');
- if(!endptr)
- return FALSE;
- name++;
- namelen = endptr - name;
- }
- else
- namelen = strlen(name);
-
- for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
- while(tok_start < no_proxy_len &&
- strchr(separator, no_proxy[tok_start]) != NULL) {
- /* Look for the beginning of the token. */
- ++tok_start;
- }
-
- if(tok_start == no_proxy_len)
- break; /* It was all trailing separator chars, no more tokens. */
-
- for(tok_end = tok_start; tok_end < no_proxy_len &&
- strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
- /* Look for the end of the token. */
- ;
-
- /* To match previous behavior, where it was necessary to specify
- * ".local.com" to prevent matching "notlocal.com", we will leave
- * the '.' off.
- */
- if(no_proxy[tok_start] == '.')
- ++tok_start;
-
- if((tok_end - tok_start) <= namelen) {
- /* Match the last part of the name to the domain we are checking. */
- const char *checkn = name + namelen - (tok_end - tok_start);
- if(strncasecompare(no_proxy + tok_start, checkn,
- tok_end - tok_start)) {
- if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
- /* We either have an exact match, or the previous character is a .
- * so it is within the same domain, so no proxy for this host.
- */
- return TRUE;
- }
- }
- } /* if((tok_end - tok_start) <= namelen) */
- } /* for(tok_start = 0; tok_start < no_proxy_len;
- tok_start = tok_end + 1) */
- } /* NO_PROXY was specified and it wasn't just an asterisk */
-
- return FALSE;
-}
#ifndef CURL_DISABLE_HTTP
/****************************************************************
@@ -2353,7 +2318,7 @@ static char *detect_proxy(struct Curl_easy *data,
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
- *envp++ = (char)tolower((int)*protop++);
+ *envp++ = Curl_raw_tolower(*protop++);
/* append _proxy */
strcpy(envp, "_proxy");
@@ -2411,13 +2376,18 @@ static CURLcode parse_proxy(struct Curl_easy *data,
int port = -1;
char *proxyuser = NULL;
char *proxypasswd = NULL;
- char *host;
+ char *host = NULL;
bool sockstype;
CURLUcode uc;
struct proxy_info *proxyinfo;
CURLU *uhp = curl_url();
CURLcode result = CURLE_OK;
char *scheme = NULL;
+#ifdef USE_UNIX_SOCKETS
+ char *path = NULL;
+ bool is_unix_proxy = FALSE;
+#endif
+
if(!uhp) {
result = CURLE_OUT_OF_MEMORY;
@@ -2542,21 +2512,54 @@ static CURLcode parse_proxy(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- Curl_safefree(proxyinfo->host.rawalloc);
- proxyinfo->host.rawalloc = host;
- if(host[0] == '[') {
- /* this is a numerical IPv6, strip off the brackets */
- size_t len = strlen(host);
- host[len-1] = 0; /* clear the trailing bracket */
- host++;
- zonefrom_url(uhp, data, conn);
+#ifdef USE_UNIX_SOCKETS
+ if(sockstype && strcasecompare(UNIX_SOCKET_PREFIX, host)) {
+ uc = curl_url_get(uhp, CURLUPART_PATH, &path, CURLU_URLDECODE);
+ if(uc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ /* path will be "/", if no path was was found */
+ if(strcmp("/", path)) {
+ is_unix_proxy = TRUE;
+ free(host);
+ host = aprintf(UNIX_SOCKET_PREFIX"%s", path);
+ if(!host) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ Curl_safefree(proxyinfo->host.rawalloc);
+ proxyinfo->host.rawalloc = host;
+ proxyinfo->host.name = host;
+ host = NULL;
+ }
+ }
+
+ if(!is_unix_proxy) {
+#endif
+ Curl_safefree(proxyinfo->host.rawalloc);
+ proxyinfo->host.rawalloc = host;
+ if(host[0] == '[') {
+ /* this is a numerical IPv6, strip off the brackets */
+ size_t len = strlen(host);
+ host[len-1] = 0; /* clear the trailing bracket */
+ host++;
+ zonefrom_url(uhp, data, conn);
+ }
+ proxyinfo->host.name = host;
+ host = NULL;
+#ifdef USE_UNIX_SOCKETS
}
- proxyinfo->host.name = host;
+#endif
error:
free(proxyuser);
free(proxypasswd);
+ free(host);
free(scheme);
+#ifdef USE_UNIX_SOCKETS
+ free(path);
+#endif
curl_url_cleanup(uhp);
return result;
}
@@ -2644,8 +2647,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
}
}
- if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
- data->set.str[STRING_NOPROXY] : no_proxy)) {
+ if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+ data->set.str[STRING_NOPROXY] : no_proxy)) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
@@ -2683,16 +2686,16 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
* connection that may exist registered to the same proxy host.
***********************************************************************/
if(proxy || socksproxy) {
+ curl_proxytype ptype = (curl_proxytype)conn->http_proxy.proxytype;
if(proxy) {
- result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
+ result = parse_proxy(data, conn, proxy, ptype);
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
if(result)
goto out;
}
if(socksproxy) {
- result = parse_proxy(data, conn, socksproxy,
- conn->socks_proxy.proxytype);
+ result = parse_proxy(data, conn, socksproxy, ptype);
/* parse_proxy copies the socks proxy string */
Curl_safefree(socksproxy);
if(result)
@@ -2842,15 +2845,15 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
- /* Allocate the user portion buffer */
- if(userp && ulen) {
+ /* Allocate the user portion buffer, which can be zero length */
+ if(userp) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the password portion buffer */
- if(!result && passwdp && plen) {
+ if(!result && passwdp && psep) {
pbuf = malloc(plen + 1);
if(!pbuf) {
free(ubuf);
@@ -2913,7 +2916,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
/* if set, we use this instead of the port possibly given in the URL */
char portbuf[16];
CURLUcode uc;
- conn->remote_port = (unsigned short)data->set.use_port;
+ conn->remote_port = data->set.use_port;
msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
if(uc)
@@ -2935,14 +2938,6 @@ static CURLcode override_login(struct Curl_easy *data,
char **passwdp = &conn->passwd;
char **optionsp = &conn->options;
-#ifndef CURL_DISABLE_NETRC
- if(data->set.use_netrc == CURL_NETRC_REQUIRED && data->state.aptr.user) {
- Curl_safefree(*userp);
- Curl_safefree(*passwdp);
- Curl_safefree(data->state.aptr.user); /* disable user+password */
- }
-#endif
-
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
@@ -2951,29 +2946,31 @@ static CURLcode override_login(struct Curl_easy *data,
}
#ifndef CURL_DISABLE_NETRC
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
+ Curl_safefree(*userp);
+ Curl_safefree(*passwdp);
+ }
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
- bool netrc_user_changed = FALSE;
- bool netrc_passwd_changed = FALSE;
int ret;
bool url_provided = FALSE;
- if(data->state.up.user) {
- /* there was a user name in the URL */
- userp = &data->state.up.user;
+ if(data->state.aptr.user) {
+ /* there was a user name in the URL. Use the URL decoded version */
+ userp = &data->state.aptr.user;
url_provided = TRUE;
}
ret = Curl_parsenetrc(conn->host.name,
userp, passwdp,
- &netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
conn->host.name, data->set.str[STRING_NETRC_FILE]);
}
else if(ret < 0) {
- return CURLE_OUT_OF_MEMORY;
+ failf(data, ".netrc parser error");
+ return CURLE_READ_ERROR;
}
else {
/* set bits.netrc TRUE to remember that we got the name from a .netrc
@@ -2986,29 +2983,35 @@ static CURLcode override_login(struct Curl_easy *data,
conn->user = strdup(*userp);
if(!conn->user)
return CURLE_OUT_OF_MEMORY;
- /* don't update the user name below */
- userp = NULL;
+ }
+ /* no user was set but a password, set a blank user */
+ if(userp && !*userp && *passwdp) {
+ *userp = strdup("");
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
}
}
#endif
/* for updated strings, we update them in the URL */
- if(userp) {
- if(*userp) {
- CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp);
+ if(*userp) {
+ CURLcode result;
+ if(data->state.aptr.user != *userp) {
+ /* nothing to do then */
+ result = Curl_setstropt(&data->state.aptr.user, *userp);
if(result)
return result;
}
- if(data->state.aptr.user) {
- uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
- CURLU_URLENCODE);
- if(uc)
- return Curl_uc_to_curlcode(uc);
- if(!*userp) {
- *userp = strdup(data->state.aptr.user);
- if(!*userp)
- return CURLE_OUT_OF_MEMORY;
- }
+ }
+ if(data->state.aptr.user) {
+ uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
+ CURLU_URLENCODE);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ if(!*userp) {
+ *userp = strdup(data->state.aptr.user);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
}
}
if(*passwdp) {
@@ -3361,131 +3364,166 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
return result;
}
-/*************************************************************
- * Resolve the address of the server or proxy
- *************************************************************/
-static CURLcode resolve_server(struct Curl_easy *data,
- struct connectdata *conn,
- bool *async)
+#ifdef USE_UNIX_SOCKETS
+static CURLcode resolve_unix(struct Curl_easy *data,
+ struct connectdata *conn,
+ char *unix_path)
{
- CURLcode result = CURLE_OK;
+ struct Curl_dns_entry *hostaddr = NULL;
+ bool longpath = FALSE;
+
+ DEBUGASSERT(unix_path);
+ DEBUGASSERT(conn->dns_entry == NULL);
+
+ /* Unix domain sockets are local. The host gets ignored, just use the
+ * specified domain socket address. Do not cache "DNS entries". There is
+ * no DNS involved and we already have the filesystem path available. */
+ hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!hostaddr)
+ return CURLE_OUT_OF_MEMORY;
+
+ hostaddr->addr = Curl_unix2addr(unix_path, &longpath,
+ conn->bits.abstract_unix_socket);
+ if(!hostaddr->addr) {
+ if(longpath)
+ /* Long paths are not supported for now */
+ failf(data, "Unix socket path too long: '%s'", unix_path);
+ free(hostaddr);
+ return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY;
+ }
+
+ hostaddr->inuse++;
+ conn->dns_entry = hostaddr;
+ return CURLE_OK;
+}
+#endif
+
+#ifndef CURL_DISABLE_PROXY
+static CURLcode resolve_proxy(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ struct Curl_dns_entry *hostaddr = NULL;
+ struct hostname *host;
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ int rc;
- DEBUGASSERT(conn);
- DEBUGASSERT(data);
- /*************************************************************
- * Resolve the name of the server or proxy
- *************************************************************/
- if(conn->bits.reuse)
- /* We're reusing the connection - no need to resolve anything, and
- idnconvert_hostname() was called already in create_conn() for the re-use
- case. */
- *async = FALSE;
+ DEBUGASSERT(conn->dns_entry == NULL);
- else {
- /* this is a fresh connect */
- int rc;
- struct Curl_dns_entry *hostaddr = NULL;
+ host = conn->bits.socksproxy ? &conn->socks_proxy.host :
+ &conn->http_proxy.host;
-#ifdef USE_UNIX_SOCKETS
- if(conn->unix_domain_socket) {
- /* Unix domain sockets are local. The host gets ignored, just use the
- * specified domain socket address. Do not cache "DNS entries". There is
- * no DNS involved and we already have the filesystem path available */
- const char *path = conn->unix_domain_socket;
-
- hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
- if(!hostaddr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- bool longpath = FALSE;
- hostaddr->addr = Curl_unix2addr(path, &longpath,
- conn->bits.abstract_unix_socket);
- if(hostaddr->addr)
- hostaddr->inuse++;
- else {
- /* Long paths are not supported for now */
- if(longpath) {
- failf(data, "Unix socket path too long: '%s'", path);
- result = CURLE_COULDNT_RESOLVE_HOST;
- }
- else
- result = CURLE_OUT_OF_MEMORY;
- free(hostaddr);
- hostaddr = NULL;
- }
- }
- }
- else
+ conn->hostname_resolve = strdup(host->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
+
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
+ &hostaddr, timeout_ms);
+ conn->dns_entry = hostaddr;
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ return CURLE_OPERATION_TIMEDOUT;
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve proxy '%s'", host->dispname);
+ return CURLE_COULDNT_RESOLVE_PROXY;
+ }
+
+ return CURLE_OK;
+}
#endif
- if(!CONN_IS_PROXIED(conn)) {
- struct hostname *connhost;
- if(conn->bits.conn_to_host)
- connhost = &conn->conn_to_host;
- else
- connhost = &conn->host;
+static CURLcode resolve_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ struct Curl_dns_entry *hostaddr = NULL;
+ struct hostname *connhost;
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ int rc;
- /* If not connecting via a proxy, extract the port from the URL, if it is
- * there, thus overriding any defaults that might have been set above. */
- if(conn->bits.conn_to_port)
- conn->port = conn->conn_to_port;
- else
- conn->port = conn->remote_port;
+ DEBUGASSERT(conn->dns_entry == NULL);
- /* Resolve target host right on */
- conn->hostname_resolve = strdup(connhost->name);
- if(!conn->hostname_resolve)
- return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
- &hostaddr, timeout_ms);
- if(rc == CURLRESOLV_PENDING)
- *async = TRUE;
-
- else if(rc == CURLRESOLV_TIMEDOUT) {
- failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
- connhost->dispname,
- Curl_timediff(Curl_now(), data->progress.t_startsingle));
- result = CURLE_OPERATION_TIMEDOUT;
- }
- else if(!hostaddr) {
- failf(data, "Could not resolve host: %s", connhost->dispname);
- result = CURLE_COULDNT_RESOLVE_HOST;
- /* don't return yet, we need to clean up the timeout first */
- }
- }
-#ifndef CURL_DISABLE_PROXY
- else {
- /* This is a proxy that hasn't been resolved yet. */
+ connhost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host;
- struct hostname * const host = conn->bits.socksproxy ?
- &conn->socks_proxy.host : &conn->http_proxy.host;
+ /* If not connecting via a proxy, extract the port from the URL, if it is
+ * there, thus overriding any defaults that might have been set above. */
+ conn->port = conn->bits.conn_to_port ? conn->conn_to_port :
+ conn->remote_port;
- /* resolve proxy */
- conn->hostname_resolve = strdup(host->name);
- if(!conn->hostname_resolve)
- return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
- &hostaddr, timeout_ms);
+ /* Resolve target host right on */
+ conn->hostname_resolve = strdup(connhost->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
- if(rc == CURLRESOLV_PENDING)
- *async = TRUE;
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
+ &hostaddr, timeout_ms);
+ conn->dns_entry = hostaddr;
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+ else if(rc == CURLRESOLV_TIMEDOUT) {
+ failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
+ connhost->dispname,
+ Curl_timediff(Curl_now(), data->progress.t_startsingle));
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else if(!hostaddr) {
+ failf(data, "Could not resolve host: %s", connhost->dispname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
- else if(rc == CURLRESOLV_TIMEDOUT)
- result = CURLE_OPERATION_TIMEDOUT;
+ return CURLE_OK;
+}
- else if(!hostaddr) {
- failf(data, "Couldn't resolve proxy '%s'", host->dispname);
- result = CURLE_COULDNT_RESOLVE_PROXY;
- /* don't return yet, we need to clean up the timeout first */
- }
- }
+/* Perform a fresh resolve */
+static CURLcode resolve_fresh(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+#ifdef USE_UNIX_SOCKETS
+ char *unix_path = conn->unix_domain_socket;
+
+#ifndef CURL_DISABLE_PROXY
+ if(!unix_path && conn->socks_proxy.host.name &&
+ !strncmp(UNIX_SOCKET_PREFIX"/",
+ conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
+ unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
#endif
- DEBUGASSERT(conn->dns_entry == NULL);
- conn->dns_entry = hostaddr;
+
+ if(unix_path) {
+ conn->transport = TRNSPRT_UNIX;
+ return resolve_unix(data, conn, unix_path);
}
+#endif
- return result;
+#ifndef CURL_DISABLE_PROXY
+ if(CONN_IS_PROXIED(conn))
+ return resolve_proxy(data, conn, async);
+#endif
+
+ return resolve_host(data, conn, async);
+}
+
+/*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+static CURLcode resolve_server(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ DEBUGASSERT(conn);
+ DEBUGASSERT(data);
+
+ /* Resolve the name of the server or proxy */
+ if(conn->bits.reuse) {
+ /* We're reusing the connection - no need to resolve anything, and
+ idnconvert_hostname() was called already in create_conn() for the re-use
+ case. */
+ *async = FALSE;
+ return CURLE_OK;
+ }
+
+ return resolve_fresh(data, conn, async);
}
/*
@@ -3502,17 +3540,6 @@ static void reuse_conn(struct Curl_easy *data,
**established** from the primary socket to a remote address. */
char local_ip[MAX_IPADR_LEN] = "";
int local_port = -1;
-#ifndef CURL_DISABLE_PROXY
- Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
- Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
-
- free(old_conn->http_proxy.host.rawalloc);
- free(old_conn->socks_proxy.host.rawalloc);
- Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
-#endif
- /* free the SSL config struct from this connection struct as this was
- allocated in vain and is targeted for destruction */
- Curl_free_primary_ssl_config(&old_conn->ssl_config);
/* get the user+password information from the old_conn struct since it may
* be new for this request even when we re-use an existing connection */
@@ -3543,20 +3570,17 @@ static void reuse_conn(struct Curl_easy *data,
old_conn->http_proxy.passwd = NULL;
old_conn->socks_proxy.passwd = NULL;
}
- Curl_safefree(old_conn->http_proxy.user);
- Curl_safefree(old_conn->socks_proxy.user);
- Curl_safefree(old_conn->http_proxy.passwd);
- Curl_safefree(old_conn->socks_proxy.passwd);
#endif
- /* host can change, when doing keepalive with a proxy or if the case is
- different this time etc */
Curl_free_idnconverted_hostname(&conn->host);
Curl_free_idnconverted_hostname(&conn->conn_to_host);
Curl_safefree(conn->host.rawalloc);
Curl_safefree(conn->conn_to_host.rawalloc);
conn->host = old_conn->host;
+ old_conn->host.rawalloc = NULL;
+ old_conn->host.encalloc = NULL;
conn->conn_to_host = old_conn->conn_to_host;
+ old_conn->conn_to_host.rawalloc = NULL;
conn->conn_to_port = old_conn->conn_to_port;
conn->remote_port = old_conn->remote_port;
Curl_safefree(conn->hostname_resolve);
@@ -3576,15 +3600,7 @@ static void reuse_conn(struct Curl_easy *data,
/* re-use init */
conn->bits.reuse = TRUE; /* yes, we're re-using here */
- Curl_safefree(old_conn->user);
- Curl_safefree(old_conn->passwd);
- Curl_safefree(old_conn->options);
- Curl_safefree(old_conn->localdev);
- Curl_llist_destroy(&old_conn->easyq, NULL);
-
-#ifdef USE_UNIX_SOCKETS
- Curl_safefree(old_conn->unix_domain_socket);
-#endif
+ conn_free(old_conn);
}
/**
@@ -3714,29 +3730,6 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result)
goto out;
- /*************************************************************
- * IDN-convert the hostnames
- *************************************************************/
- result = Curl_idnconvert_hostname(data, &conn->host);
- if(result)
- goto out;
- if(conn->bits.conn_to_host) {
- result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
- if(result)
- goto out;
- }
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy) {
- result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
- if(result)
- goto out;
- }
- if(conn->bits.socksproxy) {
- result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
- if(result)
- goto out;
- }
-#endif
/*************************************************************
* Check whether the host and the "connect to host" are equal.
@@ -3834,8 +3827,6 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
- data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
- data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
data->set.str[STRING_SSL_CIPHER_LIST];
data->set.ssl.primary.cipher_list13 =
@@ -3849,9 +3840,6 @@ static CURLcode create_conn(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
- data->set.proxy_ssl.primary.random_file =
- data->set.str[STRING_SSL_RANDOM_FILE];
- data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.proxy_ssl.primary.cipher_list =
data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
data->set.proxy_ssl.primary.cipher_list13 =
@@ -3934,10 +3922,6 @@ static CURLcode create_conn(struct Curl_easy *data,
* allocated before we can move along and use the previously existing one.
*/
reuse_conn(data, conn, conn_temp);
-#ifdef USE_SSL
- free(conn->ssl_extra);
-#endif
- free(conn); /* we don't need this anymore */
conn = conn_temp;
*in_connect = conn;
@@ -3958,13 +3942,11 @@ static CURLcode create_conn(struct Curl_easy *data,
be able to do that if we have reached the limit of how many
connections we are allowed to open. */
- if(conn->handler->flags & PROTOPT_ALPN_NPN) {
+ if(conn->handler->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
conn->bits.tls_enable_alpn = TRUE;
- if(data->set.ssl_enable_npn)
- conn->bits.tls_enable_npn = TRUE;
}
if(waitpipe)
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index 59a1c2491..ba4270d52 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -44,7 +46,8 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen);
bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
diff --git a/Utilities/cmcurl/lib/urlapi-int.h b/Utilities/cmcurl/lib/urlapi-int.h
index bd6b60175..43a83ef6e 100644
--- a/Utilities/cmcurl/lib/urlapi-int.h
+++ b/Utilities/cmcurl/lib/urlapi-int.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,13 +20,17 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
-bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme);
#ifdef DEBUGBUILD
-CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, bool);
+CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
+ bool has_scheme);
#endif
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index 2a36de6a5..7dac81c85 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -25,12 +27,12 @@
#include "urldata.h"
#include "urlapi-int.h"
#include "strcase.h"
-#include "dotdot.h"
#include "url.h"
#include "escape.h"
#include "curl_ctype.h"
#include "inet_pton.h"
#include "inet_ntop.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -66,9 +68,6 @@ struct Curl_URL {
char *path;
char *query;
char *fragment;
-
- char *scratch; /* temporary scratch area */
- char *temppath; /* temporary path pointer */
long portnum; /* the numerical version */
};
@@ -86,8 +85,6 @@ static void free_urlhandle(struct Curl_URL *u)
free(u->path);
free(u->query);
free(u->fragment);
- free(u->scratch);
- free(u->temppath);
}
/*
@@ -119,91 +116,50 @@ static const char *find_host_sep(const char *url)
}
/*
- * Decide in an encoding-independent manner whether a character in an
- * URL must be escaped. The same criterion must be used in strlen_url()
- * and strcpy_url().
+ * Decide in an encoding-independent manner whether a character in a URL must
+ * be escaped. This is used in urlencode_str().
*/
static bool urlchar_needs_escaping(int c)
{
return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
}
-/*
- * strlen_url() returns the length of the given URL if the spaces within the
- * URL were properly URL encoded.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static size_t strlen_url(const char *url, bool relative)
-{
- const unsigned char *ptr;
- size_t newlen = 0;
- bool left = TRUE; /* left side of the ? */
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(ptr = (unsigned char *)url; *ptr; ptr++) {
-
- if(ptr < host_sep) {
- ++newlen;
- continue;
- }
-
- if(*ptr == ' ') {
- if(left)
- newlen += 3;
- else
- newlen++;
- continue;
- }
-
- if (*ptr == '?')
- left = FALSE;
-
- if(urlchar_needs_escaping(*ptr))
- newlen += 2;
-
- newlen++;
- }
-
- return newlen;
-}
-
-/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
- * the source URL accordingly.
+/* urlencode_str() writes data into an output dynbuf and URL-encodes the
+ * spaces in the source URL accordingly.
+ *
* URL encoding should be skipped for host names, otherwise IDN resolution
* will fail.
*/
-static void strcpy_url(char *output, const char *url, bool relative)
+static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
+ size_t len, bool relative,
+ bool query)
{
/* we must add this with whitespace-replacing */
- bool left = TRUE;
+ bool left = !query;
const unsigned char *iptr;
- char *optr = output;
const unsigned char *host_sep = (const unsigned char *) url;
if(!relative)
host_sep = (const unsigned char *) find_host_sep(url);
for(iptr = (unsigned char *)url; /* read from here */
- *iptr; /* until zero byte */
- iptr++) {
+ len; iptr++, len--) {
if(iptr < host_sep) {
- *optr++ = *iptr;
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
continue;
}
if(*iptr == ' ') {
if(left) {
- *optr++='%'; /* add a '%' */
- *optr++='2'; /* add a '2' */
- *optr++='0'; /* add a '0' */
+ if(Curl_dyn_addn(o, "%20", 3))
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ else {
+ if(Curl_dyn_addn(o, "+", 1))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++='+'; /* add a '+' here */
continue;
}
@@ -211,22 +167,28 @@ static void strcpy_url(char *output, const char *url, bool relative)
left = FALSE;
if(urlchar_needs_escaping(*iptr)) {
- msnprintf(optr, 4, "%%%02x", *iptr);
- optr += 3;
+ if(Curl_dyn_addf(o, "%%%02x", *iptr))
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ else {
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++ = *iptr;
}
- *optr = 0; /* null-terminate output buffer */
+ return CURLUE_OK;
}
/*
- * Returns true if the given URL is absolute (as opposed to relative). Returns
- * the scheme in the buffer if TRUE and 'buf' is non-NULL. The buflen must
- * be larger than MAX_SCHEME_LEN if buf is set.
+ * Returns the length of the scheme if the given URL is absolute (as opposed
+ * to relative). Stores the scheme in the buffer if TRUE and 'buf' is
+ * non-NULL. The buflen must be larger than MAX_SCHEME_LEN if buf is set.
+ *
+ * If 'guess_scheme' is TRUE, it means the URL might be provided without
+ * scheme.
*/
-bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme)
{
int i;
DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN));
@@ -234,8 +196,8 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
if(buf)
buf[0] = 0; /* always leave a defined value in buf */
#ifdef WIN32
- if(STARTS_WITH_DRIVE_PREFIX(url))
- return FALSE;
+ if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
+ return 0;
#endif
for(i = 0; i < MAX_SCHEME_LEN; ++i) {
char s = url[i];
@@ -248,16 +210,22 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
break;
}
}
- if(i && (url[i] == ':') && (url[i + 1] == '/')) {
+ if(i && (url[i] == ':') && ((url[i + 1] == '/') || !guess_scheme)) {
+ /* If this does not guess scheme, the scheme always ends with the colon so
+ that this also detects data: URLs etc. In guessing mode, data: could
+ be the host name "data" with a specified port number. */
+
+ /* the length of the scheme is the name part only */
+ size_t len = i;
if(buf) {
buf[i] = 0;
while(i--) {
- buf[i] = (char)TOLOWER(url[i]);
+ buf[i] = Curl_raw_tolower(url[i]);
}
}
- return TRUE;
+ return len;
}
- return FALSE;
+ return 0;
}
/*
@@ -265,34 +233,26 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
* URL-encodes any spaces.
* The returned pointer must be freed by the caller unless NULL
* (returns NULL on out of memory).
+ *
+ * Note that this function destroys the 'base' string.
*/
-static char *concat_url(const char *base, const char *relurl)
+static char *concat_url(char *base, const char *relurl)
{
/***
TRY to append this new path to the old URL
to the right of the host part. Oh crap, this is doomed to cause
problems in the future...
*/
- char *newest;
+ struct dynbuf newest;
char *protsep;
char *pathsep;
- size_t newlen;
bool host_changed = FALSE;
-
const char *useurl = relurl;
- size_t urllen;
-
- /* we must make our own copy of the URL to play with, as it may
- point to read-only data */
- char *url_clone = strdup(base);
-
- if(!url_clone)
- return NULL; /* skip out of this NOW */
/* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
+ protsep = strstr(base, "//");
if(!protsep)
- protsep = url_clone;
+ protsep = base;
else
protsep += 2; /* pass the slashes */
@@ -385,38 +345,24 @@ static char *concat_url(const char *base, const char *relurl)
}
}
- /* If the new part contains a space, this is a mighty stupid redirect
- but we still make an effort to do "right". To the left of a '?'
- letter we replace each space with %20 while it is replaced with '+'
- on the right side of the '?' letter.
- */
- newlen = strlen_url(useurl, !host_changed);
-
- urllen = strlen(url_clone);
-
- newest = malloc(urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
-
- if(!newest) {
- free(url_clone); /* don't leak this */
- return NULL;
- }
+ Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
/* copy over the root url part */
- memcpy(newest, url_clone, urllen);
+ if(Curl_dyn_add(&newest, base))
+ return NULL;
/* check if we need to append a slash */
if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
;
- else
- newest[urllen++]='/';
+ else {
+ if(Curl_dyn_addn(&newest, "/", 1))
+ return NULL;
+ }
/* then append the new piece on the right side */
- strcpy_url(&newest[urllen], useurl, !host_changed);
-
- free(url_clone);
+ urlencode_str(&newest, useurl, strlen(useurl), !host_changed, FALSE);
- return newest;
+ return Curl_dyn_ptr(&newest);
}
/* scan for byte values < 31 or 127 */
@@ -450,7 +396,7 @@ static bool junkscan(const char *part, unsigned int flags)
*
*/
static CURLUcode parse_hostname_login(struct Curl_URL *u,
- char **hostname,
+ struct dynbuf *host,
unsigned int flags)
{
CURLUcode result = CURLUE_OK;
@@ -460,27 +406,31 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
char *optionsp = NULL;
const struct Curl_handler *h = NULL;
- /* At this point, we're hoping all the other special cases have
- * been taken care of, so conn->host.name is at most
- * [user[:password][;options]]@]hostname
+ /* At this point, we assume all the other special cases have been taken
+ * care of, so the host is at most
+ *
+ * [user[:password][;options]]@]hostname
*
* We need somewhere to put the embedded details, so do that first.
*/
- char *ptr = strchr(*hostname, '@');
- char *login = *hostname;
+ char *login = Curl_dyn_ptr(host);
+ char *ptr;
+ DEBUGASSERT(login);
+
+ ptr = strchr(login, '@');
if(!ptr)
goto out;
/* We will now try to extract the
* possible login information in a string like:
* ftp://user:password@ftp.my.site:8021/README */
- *hostname = ++ptr;
+ ptr++;
/* if this is a known scheme, get some details */
if(u->scheme)
- h = Curl_builtin_scheme(u->scheme);
+ h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. Note that 'h' might be NULL! */
@@ -522,6 +472,10 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
u->options = optionsp;
}
+ /* move the name to the start of the host buffer */
+ if(Curl_dyn_tail(host, strlen(ptr)))
+ return CURLUE_OUT_OF_MEMORY;
+
return CURLUE_OK;
out:
@@ -535,13 +489,13 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
return result;
}
-UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
char *portptr = NULL;
char endbracket;
int len;
-
+ char *hostname = Curl_dyn_ptr(host);
/*
* Find the end of an IPv6 address, either on the ']' ending bracket or
* a percent-encoded zone index.
@@ -578,6 +532,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
char *rest;
long port;
char portbuf[7];
+ size_t keep = portptr - hostname;
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
@@ -586,15 +541,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
Don't do it if the URL has no scheme, to make something that looks like
a scheme not work!
*/
- if(!portptr[1]) {
- *portptr = '\0';
+ Curl_dyn_setlen(host, keep);
+ portptr++;
+ if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
- }
- if(!ISDIGIT(portptr[1]))
+ if(!ISDIGIT(*portptr))
return CURLUE_BAD_PORT_NUMBER;
- port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
+ port = strtol(portptr, &rest, 10); /* Port number must be decimal */
if(port > 0xffff)
return CURLUE_BAD_PORT_NUMBER;
@@ -602,7 +557,6 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
if(rest[0])
return CURLUE_BAD_PORT_NUMBER;
- *portptr++ = '\0'; /* cut off the name there */
*rest = 0;
/* generate a new port number string to get rid of leading zeroes etc */
msnprintf(portbuf, sizeof(portbuf), "%ld", port);
@@ -615,12 +569,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
return CURLUE_OK;
}
-static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
+static CURLUcode hostname_check(struct Curl_URL *u, char *hostname,
+ size_t hlen) /* length of hostname */
{
size_t len;
- size_t hlen = strlen(hostname);
+ DEBUGASSERT(hostname);
- if(hostname[0] == '[') {
+ if(!hostname[0])
+ return CURLUE_NO_HOST;
+ else if(hostname[0] == '[') {
const char *l = "0123456789abcdefABCDEF:.";
if(hlen < 4) /* '[::]' is the shortest possible valid string */
return CURLUE_BAD_IPV6;
@@ -679,13 +636,11 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
}
else {
/* letters from the second string are not ok */
- len = strcspn(hostname, " \r\n\t/:#?!@");
+ len = strcspn(hostname, " \r\n\t/:#?!@{}[]\\$\'\"^`*<>=;,");
if(hlen != len)
/* hostname with bad content */
return CURLUE_BAD_HOSTNAME;
}
- if(!hostname[0])
- return CURLUE_NO_HOST;
return CURLUE_OK;
}
@@ -779,79 +734,230 @@ static bool ipv4_normalize(const char *hostname, char *outp, size_t olen)
return TRUE;
}
-/* return strdup'ed version in 'outp', possibly percent decoded */
-static CURLUcode decode_host(char *hostname, char **outp)
+/* if necessary, replace the host content with a URL decoded version */
+static CURLUcode decode_host(struct dynbuf *host)
{
char *per = NULL;
- if(hostname[0] != '[')
+ const char *hostname = Curl_dyn_ptr(host);
+ if(hostname[0] == '[')
/* only decode if not an ipv6 numerical */
- per = strchr(hostname, '%');
- if(!per) {
- *outp = strdup(hostname);
- if(!*outp)
- return CURLUE_OUT_OF_MEMORY;
- }
+ return CURLUE_OK;
+ per = strchr(hostname, '%');
+ if(!per)
+ /* nothing to decode */
+ return CURLUE_OK;
else {
- /* might be encoded */
+ /* encoded */
size_t dlen;
- CURLcode result = Curl_urldecode(hostname, 0, outp, &dlen, REJECT_CTRL);
+ char *decoded;
+ CURLcode result = Curl_urldecode(hostname, 0, &decoded, &dlen,
+ REJECT_CTRL);
if(result)
return CURLUE_BAD_HOSTNAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addn(host, decoded, dlen);
+ free(decoded);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
return CURLUE_OK;
}
-static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
+/*
+ * "Remove Dot Segments"
+ * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
+ */
+
+/*
+ * dedotdotify()
+ * @unittest: 1395
+ *
+ * This function gets a null-terminated path with dot and dotdot sequences
+ * passed in and strips them off according to the rules in RFC 3986 section
+ * 5.2.4.
+ *
+ * The function handles a query part ('?' + stuff) appended but it expects
+ * that fragments ('#' + stuff) have already been cut off.
+ *
+ * RETURNS
+ *
+ * an allocated dedotdotified output string
+ */
+UNITTEST char *dedotdotify(const char *input, size_t clen);
+UNITTEST char *dedotdotify(const char *input, size_t clen)
{
- char *path;
- bool path_alloced = FALSE;
+ char *out = malloc(clen + 1);
+ char *outptr;
+ const char *orginput = input;
+ char *queryp;
+ if(!out)
+ return NULL; /* out of memory */
+
+ *out = 0; /* null-terminates, for inputs like "./" */
+ outptr = out;
+
+ if(!*input)
+ /* zero length input string, return that */
+ return out;
+
+ /*
+ * To handle query-parts properly, we must find it and remove it during the
+ * dotdot-operation and then append it again at the end to the output
+ * string.
+ */
+ queryp = strchr(input, '?');
+
+ do {
+ bool dotdot = TRUE;
+ if(*input == '.') {
+ /* A. If the input buffer begins with a prefix of "../" or "./", then
+ remove that prefix from the input buffer; otherwise, */
+
+ if(!strncmp("./", input, 2)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strncmp("../", input, 3)) {
+ input += 3;
+ clen -= 3;
+ }
+ /* D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise, */
+
+ else if(!strcmp(".", input) || !strcmp("..", input) ||
+ !strncmp(".?", input, 2) || !strncmp("..?", input, 3)) {
+ *out = 0;
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else if(*input == '/') {
+ /* B. if the input buffer begins with a prefix of "/./" or "/.", where
+ "." is a complete path segment, then replace that prefix with "/" in
+ the input buffer; otherwise, */
+ if(!strncmp("/./", input, 3)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strcmp("/.", input) || !strncmp("/.?", input, 3)) {
+ *outptr++ = '/';
+ *outptr = 0;
+ break;
+ }
+
+ /* C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that prefix with
+ "/" in the input buffer and remove the last segment and its
+ preceding "/" (if any) from the output buffer; otherwise, */
+
+ else if(!strncmp("/../", input, 4)) {
+ input += 3;
+ clen -= 3;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* null-terminate where it stops */
+ }
+ else if(!strcmp("/..", input) || !strncmp("/..?", input, 4)) {
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr++ = '/';
+ *outptr = 0; /* null-terminate where it stops */
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else
+ dotdot = FALSE;
+
+ if(!dotdot) {
+ /* E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if any) and
+ any subsequent characters up to, but not including, the next "/"
+ character or the end of the input buffer. */
+
+ do {
+ *outptr++ = *input++;
+ clen--;
+ } while(*input && (*input != '/') && (*input != '?'));
+ *outptr = 0;
+ }
+
+ /* continue until end of input string OR, if there is a terminating
+ query part, stop there */
+ } while(*input && (!queryp || (input < queryp)));
+
+ if(queryp) {
+ size_t qlen;
+ /* There was a query part, append that to the output. */
+ size_t oindex = queryp - orginput;
+ qlen = strlen(&orginput[oindex]);
+ memcpy(outptr, &orginput[oindex], qlen + 1); /* include zero byte */
+ }
+
+ return out;
+}
+
+static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
+{
+ const char *path;
+ size_t pathlen;
bool uncpath = FALSE;
- char *hostname;
char *query = NULL;
char *fragment = NULL;
- CURLUcode result;
- bool url_has_scheme = FALSE;
char schemebuf[MAX_SCHEME_LEN + 1];
const char *schemep = NULL;
size_t schemelen = 0;
size_t urllen;
+ CURLUcode result = CURLUE_OK;
+ size_t fraglen = 0;
+ struct dynbuf host;
DEBUGASSERT(url);
+ Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
+
/*************************************************************
* Parse the URL.
************************************************************/
/* allocate scratch area */
urllen = strlen(url);
- if(urllen > CURL_MAX_INPUT_LENGTH)
+ if(urllen > CURL_MAX_INPUT_LENGTH) {
/* excessive input length */
- return CURLUE_MALFORMED_INPUT;
-
- path = u->scratch = malloc(urllen * 2 + 2);
- if(!path)
- return CURLUE_OUT_OF_MEMORY;
-
- hostname = &path[urllen + 1];
- hostname[0] = 0;
-
- if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) {
- url_has_scheme = TRUE;
- schemelen = strlen(schemebuf);
+ result = CURLUE_MALFORMED_INPUT;
+ goto fail;
}
+ schemelen = Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf),
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME));
+
/* handle the file: scheme */
- if(url_has_scheme && !strcmp(schemebuf, "file")) {
- if(urllen <= 6)
+ if(schemelen && !strcmp(schemebuf, "file")) {
+ if(urllen <= 6) {
/* file:/ is not enough to actually be a complete file: URL */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
/* path has been allocated large enough to hold this */
- strcpy(path, &url[5]);
+ path = (char *)&url[5];
- u->scheme = strdup("file");
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ schemep = u->scheme = strdup("file");
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
@@ -861,7 +967,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
*/
if(path[0] == '/' && path[1] == '/') {
/* swallow the two slashes */
- char *ptr = &path[2];
+ const char *ptr = &path[2];
/*
* According to RFC 8089, a file: URL can be reliably dereferenced if:
@@ -897,13 +1003,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
chars, and the delimiting slash character must be appended to the
host name */
path = strpbrk(ptr, "/\\:*?\"<>|");
- if(!path || *path != '/')
- return CURLUE_BAD_FILE_URL;
+ if(!path || *path != '/') {
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
len = path - ptr;
if(len) {
- memcpy(hostname, ptr, len);
- hostname[len] = 0;
+ if(Curl_dyn_addn(&host, ptr, len)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
uncpath = TRUE;
}
@@ -911,7 +1021,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
#else
/* Invalid file://hostname/, expected localhost or 127.0.0.1 or
none */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
#endif
}
}
@@ -920,7 +1031,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
}
if(!uncpath)
- hostname = NULL; /* no host for file: URLs by default */
+ /* no host for file: URLs by default */
+ Curl_dyn_reset(&host);
#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
/* Don't allow Windows drive letters when not in Windows.
@@ -928,13 +1040,14 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
STARTS_WITH_URL_DRIVE_PREFIX(path)) {
/* File drive letters are only accepted in MSDOS/Windows */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
}
#else
/* If the path starts with a slash and a drive letter, ditch the slash */
if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
/* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, &path[1], strlen(&path[1]) + 1);
+ path++;
}
#endif
@@ -944,32 +1057,39 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
const char *p;
const char *hostp;
size_t len;
- path[0] = 0;
- if(url_has_scheme) {
+ if(schemelen) {
int i = 0;
p = &url[schemelen + 1];
while(p && (*p == '/') && (i < 4)) {
p++;
i++;
}
- if((i < 1) || (i>3))
- /* less than one or more than three slashes */
- return CURLUE_BAD_SLASHES;
schemep = schemebuf;
- if(!Curl_builtin_scheme(schemep) &&
- !(flags & CURLU_NON_SUPPORT_SCHEME))
- return CURLUE_UNSUPPORTED_SCHEME;
+ if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+ !(flags & CURLU_NON_SUPPORT_SCHEME)) {
+ result = CURLUE_UNSUPPORTED_SCHEME;
+ goto fail;
+ }
- if(junkscan(schemep, flags))
- return CURLUE_BAD_SCHEME;
+ if((i < 1) || (i>3)) {
+ /* less than one or more than three slashes */
+ result = CURLUE_BAD_SLASHES;
+ goto fail;
+ }
+ if(junkscan(schemep, flags)) {
+ result = CURLUE_BAD_SCHEME;
+ goto fail;
+ }
}
else {
/* no scheme! */
- if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
- return CURLUE_BAD_SCHEME;
+ if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) {
+ result = CURLUE_BAD_SCHEME;
+ goto fail;
+ }
if(flags & CURLU_DEFAULT_SCHEME)
schemep = DEFAULT_SCHEME;
@@ -986,122 +1106,169 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
len = p - hostp;
if(len) {
- memcpy(hostname, hostp, len);
- hostname[len] = 0;
+ if(Curl_dyn_addn(&host, hostp, len)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
else {
- if(!(flags & CURLU_NO_AUTHORITY))
- return CURLUE_NO_HOST;
+ if(!(flags & CURLU_NO_AUTHORITY)) {
+ result = CURLUE_NO_HOST;
+ goto fail;
+ }
}
- strcpy(path, p);
+ path = (char *)p;
if(schemep) {
u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
}
- if((flags & CURLU_URLENCODE) && path[0]) {
- /* worst case output length is 3x the original! */
- char *newp = malloc(strlen(path) * 3);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
- path_alloced = TRUE;
- strcpy_url(newp, path, TRUE); /* consider it relative */
- u->temppath = path = newp;
- }
-
fragment = strchr(path, '#');
if(fragment) {
- *fragment++ = 0;
- if(junkscan(fragment, flags))
- return CURLUE_BAD_FRAGMENT;
- if(fragment[0]) {
- u->fragment = strdup(fragment);
- if(!u->fragment)
- return CURLUE_OUT_OF_MEMORY;
+ fraglen = strlen(fragment);
+ if(fraglen > 1) {
+ /* skip the leading '#' in the copy but include the terminating null */
+ u->fragment = Curl_memdup(fragment + 1, fraglen);
+ if(!u->fragment) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ if(junkscan(u->fragment, flags)) {
+ result = CURLUE_BAD_FRAGMENT;
+ goto fail;
+ }
}
}
query = strchr(path, '?');
- if(query) {
- *query++ = 0;
- if(junkscan(query, flags))
- return CURLUE_BAD_QUERY;
- /* done even if the query part is a blank string */
- u->query = strdup(query);
- if(!u->query)
- return CURLUE_OUT_OF_MEMORY;
- }
+ if(query && (!fragment || (query < fragment))) {
+ size_t qlen = strlen(query) - fraglen; /* includes '?' */
+ pathlen = strlen(path) - qlen - fraglen;
+ if(qlen > 1) {
+ if(qlen && (flags & CURLU_URLENCODE)) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ /* skip the leading question mark */
+ if(urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query = Curl_dyn_ptr(&enc);
+ }
+ else {
+ u->query = Curl_memdup(query + 1, qlen);
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query[qlen - 1] = 0;
+ }
- if(junkscan(path, flags))
- return CURLUE_BAD_PATH;
+ if(junkscan(u->query, flags)) {
+ result = CURLUE_BAD_QUERY;
+ goto fail;
+ }
+ }
+ else {
+ /* single byte query */
+ u->query = strdup("");
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ else
+ pathlen = strlen(path) - fraglen;
+
+ if(pathlen && (flags & CURLU_URLENCODE)) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, path, pathlen, TRUE, FALSE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ pathlen = Curl_dyn_len(&enc);
+ path = u->path = Curl_dyn_ptr(&enc);
+ }
- if(!path[0])
- /* if there's no path left set, unset */
+ if(!pathlen) {
+ /* there is no path left, unset */
path = NULL;
+ }
else {
+ if(!u->path) {
+ u->path = Curl_memdup(path, pathlen + 1);
+ if(!u->path) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->path[pathlen] = 0;
+ path = u->path;
+ }
+ else if(flags & CURLU_URLENCODE)
+ /* it might have encoded more than just the path so cut it */
+ u->path[pathlen] = 0;
+
+ if(junkscan(u->path, flags)) {
+ result = CURLUE_BAD_PATH;
+ goto fail;
+ }
+
if(!(flags & CURLU_PATH_AS_IS)) {
/* remove ../ and ./ sequences according to RFC3986 */
- char *newp = Curl_dedotdotify(path);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
-
- if(strcmp(newp, path)) {
- /* if we got a new version */
- if(path_alloced)
- Curl_safefree(u->temppath);
- u->temppath = path = newp;
- path_alloced = TRUE;
+ char *newp = dedotdotify((char *)path, pathlen);
+ if(!newp) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
}
- else
- free(newp);
+ free(u->path);
+ u->path = newp;
}
-
- u->path = path_alloced?path:strdup(path);
- if(!u->path)
- return CURLUE_OUT_OF_MEMORY;
- u->temppath = NULL; /* used now */
}
- if(hostname) {
+ if(Curl_dyn_len(&host)) {
char normalized_ipv4[sizeof("255.255.255.255") + 1];
/*
* Parse the login details and strip them out of the host name.
*/
- result = parse_hostname_login(u, &hostname, flags);
+ result = parse_hostname_login(u, &host, flags);
+ if(!result)
+ result = Curl_parse_port(u, &host, schemelen);
if(result)
- return result;
+ goto fail;
- result = Curl_parse_port(u, hostname, url_has_scheme);
- if(result)
- return result;
-
- if(junkscan(hostname, flags))
- return CURLUE_BAD_HOSTNAME;
+ if(junkscan(Curl_dyn_ptr(&host), flags)) {
+ result = CURLUE_BAD_HOSTNAME;
+ goto fail;
+ }
- if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) {
- /* Skip hostname check, it's allowed to be empty. */
- u->host = strdup("");
+ if(ipv4_normalize(Curl_dyn_ptr(&host),
+ normalized_ipv4, sizeof(normalized_ipv4))) {
+ Curl_dyn_reset(&host);
+ if(Curl_dyn_add(&host, normalized_ipv4)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
else {
- if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4)))
- u->host = strdup(normalized_ipv4);
- else {
- result = decode_host(hostname, &u->host);
- if(result)
- return result;
- result = hostname_check(u, u->host);
- if(result)
- return result;
- }
+ result = decode_host(&host);
+ if(!result)
+ result = hostname_check(u, Curl_dyn_ptr(&host), Curl_dyn_len(&host));
+ if(result)
+ goto fail;
}
- if(!u->host)
- return CURLUE_OUT_OF_MEMORY;
+
if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+ const char *hostname = Curl_dyn_ptr(&host);
/* legacy curl-style guess based on host name */
if(checkprefix("ftp.", hostname))
schemep = "ftp";
@@ -1119,27 +1286,26 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
schemep = "http";
u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ else if(flags & CURLU_NO_AUTHORITY) {
+ /* allowed to be empty. */
+ if(Curl_dyn_add(&host, "")) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
}
}
- Curl_safefree(u->scratch);
- Curl_safefree(u->temppath);
-
- return CURLUE_OK;
-}
+ u->host = Curl_dyn_ptr(&host);
-/*
- * Parse the URL and set the relevant members of the Curl_URL struct.
- */
-static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
-{
- CURLUcode result = seturl(url, u, flags);
- if(result) {
- free_urlhandle(u);
- memset(u, 0, sizeof(struct Curl_URL));
- }
+ return result;
+ fail:
+ Curl_dyn_free(&host);
+ free_urlhandle(u);
return result;
}
@@ -1157,8 +1323,6 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
free_urlhandle(u);
*u = tmpurl;
}
- else
- free_urlhandle(&tmpurl);
return result;
}
@@ -1257,7 +1421,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there's no stored port number, but asked to deliver
a default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h) {
msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
@@ -1267,7 +1431,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there is a stored port number, but ask to inhibit if
it matches the default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h && (h->defport == u->portnum) &&
(flags & CURLU_NO_DEFAULT_PORT))
ptr = NULL;
@@ -1313,7 +1477,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
else
return CURLUE_NO_SCHEME;
- h = Curl_builtin_scheme(scheme);
+ h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(!port && (flags & CURLU_DEFAULT_PORT)) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
@@ -1336,14 +1500,13 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
if(u->host[0] == '[') {
if(u->zoneid) {
/* make it '[ host %25 zoneid ]' */
+ struct dynbuf enc;
size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 3 + strlen(u->zoneid) + 1;
- allochost = malloc(alen);
- if(!allochost)
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(Curl_dyn_addf(&enc, "%.*s%%25%s]", (int)hostlen - 1, u->host,
+ u->zoneid))
return CURLUE_OUT_OF_MEMORY;
- memcpy(allochost, u->host, hostlen - 1);
- msnprintf(&allochost[hostlen - 1], alen - hostlen + 1,
- "%%25%s]", u->zoneid);
+ allochost = Curl_dyn_ptr(&enc);
}
}
else if(urlencode) {
@@ -1354,32 +1517,32 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
else {
/* only encode '%' in output host name */
char *host = u->host;
- size_t pcount = 0;
+ bool percent = FALSE;
/* first, count number of percents present in the name */
while(*host) {
- if(*host == '%')
- pcount++;
+ if(*host == '%') {
+ percent = TRUE;
+ break;
+ }
host++;
}
- /* if there were percents, encode the host name */
- if(pcount) {
- size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 2 * pcount + 1;
- char *o = allochost = malloc(alen);
- if(!allochost)
- return CURLUE_OUT_OF_MEMORY;
-
+ /* if there were percent(s), encode the host name */
+ if(percent) {
+ struct dynbuf enc;
+ CURLcode result;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
host = u->host;
while(*host) {
- if(*host == '%') {
- memcpy(o, "%25", 3);
- o += 3;
- host++;
- continue;
- }
- *o++ = *host++;
+ if(*host == '%')
+ result = Curl_dyn_addn(&enc, "%25", 3);
+ else
+ result = Curl_dyn_addn(&enc, host, 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
+ host++;
}
- *o = '\0';
+ free(u->host);
+ u->host = Curl_dyn_ptr(&enc);
}
}
@@ -1412,13 +1575,15 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
break;
}
if(ptr) {
- *part = strdup(ptr);
+ size_t partlen = strlen(ptr);
+ size_t i = 0;
+ *part = Curl_memdup(ptr, partlen + 1);
if(!*part)
return CURLUE_OUT_OF_MEMORY;
if(plusdecode) {
/* convert + to space */
- char *plus;
- for(plus = *part; *plus; ++plus) {
+ char *plus = *part;
+ for(i = 0; i < partlen; ++plus, i++) {
if(*plus == '+')
*plus = ' ';
}
@@ -1435,7 +1600,18 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
return CURLUE_URLDECODE;
}
*part = decoded;
+ partlen = dlen;
}
+ if(urlencode) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, *part, partlen, TRUE,
+ what == CURLUPART_QUERY))
+ return CURLUE_OUT_OF_MEMORY;
+ free(*part);
+ *part = Curl_dyn_ptr(&enc);
+ }
+
return CURLUE_OK;
}
else
@@ -1497,6 +1673,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(storep && *storep) {
Curl_safefree(*storep);
}
+ else if(!storep) {
+ free_urlhandle(u);
+ memset(u, 0, sizeof(struct Curl_URL));
+ }
return CURLUE_OK;
}
@@ -1507,7 +1687,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_BAD_SCHEME;
if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
/* verify that it is a fine scheme */
- !Curl_builtin_scheme(part))
+ !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
@@ -1573,7 +1753,9 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
/* if the new thing is absolute or the old one is not
* (we could not get an absolute url in 'oldurl'),
* then replace the existing with the new. */
- if(Curl_is_absolute_url(part, NULL, 0)
+ if(Curl_is_absolute_url(part, NULL, 0,
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME))
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags);
}
@@ -1603,14 +1785,16 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(urlencode) {
const unsigned char *i;
- char *o;
- char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
- if(!enc)
- return CURLUE_OUT_OF_MEMORY;
- for(i = (const unsigned char *)part, o = enc; *i; i++) {
+ struct dynbuf enc;
+
+ Curl_dyn_init(&enc, nalloc * 3 + 1);
+
+ for(i = (const unsigned char *)part; *i; i++) {
+ CURLcode result;
if((*i == ' ') && plusencode) {
- *o = '+';
- o++;
+ result = Curl_dyn_addn(&enc, "+", 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else if(Curl_isunreserved(*i) ||
((*i == '/') && urlskipslash) ||
@@ -1618,16 +1802,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
- *o = *i;
- o++;
+ result = Curl_dyn_addn(&enc, i, 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else {
- msnprintf(o, 4, "%%%02x", *i);
- o += 3;
+ result = Curl_dyn_addf(&enc, "%%%02x", *i);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
}
- *o = 0; /* null-terminate */
- newp = enc;
+ newp = Curl_dyn_ptr(&enc);
}
else {
char *p;
@@ -1639,8 +1824,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
/* make sure percent encoded are lower case */
if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
(ISUPPER(p[1]) || ISUPPER(p[2]))) {
- p[1] = (char)TOLOWER(p[1]);
- p[2] = (char)TOLOWER(p[2]);
+ p[1] = Curl_raw_tolower(p[1]);
+ p[2] = Curl_raw_tolower(p[2]);
p += 3;
}
else
@@ -1649,34 +1834,41 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
if(appendquery) {
- /* Append the string onto the old query. Add a '&' separator if none is
- present at the end of the exsting query already */
+ /* Append the 'newp' string onto the old query. Add a '&' separator if
+ none is present at the end of the existing query already */
+
size_t querylen = u->query ? strlen(u->query) : 0;
bool addamperand = querylen && (u->query[querylen -1] != '&');
if(querylen) {
- size_t newplen = strlen(newp);
- char *p = malloc(querylen + addamperand + newplen + 1);
- if(!p) {
- free((char *)newp);
- return CURLUE_OUT_OF_MEMORY;
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+
+ if(Curl_dyn_addn(&enc, u->query, querylen)) /* add original query */
+ goto nomem;
+
+ if(addamperand) {
+ if(Curl_dyn_addn(&enc, "&", 1))
+ goto nomem;
}
- strcpy(p, u->query); /* original query */
- if(addamperand)
- p[querylen] = '&'; /* ampersand */
- strcpy(&p[querylen + addamperand], newp); /* new suffix */
+ if(Curl_dyn_add(&enc, newp))
+ goto nomem;
free((char *)newp);
free(*storep);
- *storep = p;
+ *storep = Curl_dyn_ptr(&enc);
return CURLUE_OK;
+ nomem:
+ free((char *)newp);
+ return CURLUE_OUT_OF_MEMORY;
}
}
if(what == CURLUPART_HOST) {
- if(0 == strlen(newp) && (flags & CURLU_NO_AUTHORITY)) {
+ size_t n = strlen(newp);
+ if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it's allowed to be empty. */
}
else {
- if(hostname_check(u, (char *)newp)) {
+ if(hostname_check(u, (char *)newp, n)) {
free((char *)newp);
return CURLUE_BAD_HOSTNAME;
}
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 584434d77..1d430b5e8 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* This file is for lib internal stuff */
@@ -51,6 +53,33 @@
#define PORT_GOPHER 70
#define PORT_MQTT 1883
+#ifdef USE_WEBSOCKETS
+/* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number,
+ * the rest are internal information. If we use higher bits we only do this on
+ * platforms that have a >= 64 bit type and then we use such a type for the
+ * protocol fields in the protocol handler.
+ */
+#define CURLPROTO_WS (1<<30)
+#define CURLPROTO_WSS ((curl_prot_t)1<<31)
+#else
+#define CURLPROTO_WS 0
+#define CURLPROTO_WSS 0
+#endif
+
+/* This should be undefined once we need bit 32 or higher */
+#define PROTO_TYPE_SMALL
+
+#ifndef PROTO_TYPE_SMALL
+typedef curl_off_t curl_prot_t;
+#else
+typedef unsigned int curl_prot_t;
+#endif
+
+/* This mask is for all the old protocols that are provided and defined in the
+ public header and shall exclude protocols added since which are not exposed
+ in the API */
+#define CURLPROTO_MASK (0x3ffffff)
+
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
#define DICT_MATCH3 "/FIND:"
@@ -64,7 +93,8 @@
/* Convenience defines for checking protocols or their SSL based version. Each
protocol handler should only ever have a single CURLPROTO_ in its protocol
field. */
-#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS)
+#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_WS| \
+ CURLPROTO_WSS)
#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS)
#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S)
#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS)
@@ -155,10 +185,10 @@ typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
# endif
#endif
-#ifdef HAVE_LIBSSH2_H
+#ifdef USE_LIBSSH2
#include <libssh2.h>
#include <libssh2_sftp.h>
-#endif /* HAVE_LIBSSH2_H */
+#endif /* USE_LIBSSH2 */
#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX CURL_MAX_READ_SIZE
@@ -180,15 +210,6 @@ typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
-/* the type we use for storing a single boolean bit */
-#ifdef _MSC_VER
-typedef bool bit;
-#define BIT(x) bool x
-#else
-typedef unsigned int bit;
-#define BIT(x) bit x:1
-#endif
-
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
struct krb5buffer {
@@ -248,8 +269,6 @@ struct ssl_primary_config {
char *CAfile; /* certificate to verify peer against */
char *issuercert; /* optional issuer certificate filename */
char *clientcert;
- char *random_file; /* path to file containing "random" data */
- char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
@@ -327,11 +346,11 @@ struct digestdata {
char *nonce;
char *cnonce;
char *realm;
- int algo;
char *opaque;
char *qop;
char *algorithm;
int nc; /* nonce count */
+ unsigned char algo;
BIT(stale); /* set true for re-negotiation */
BIT(userhash);
#endif
@@ -516,9 +535,7 @@ struct ConnectBits {
connection */
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(tls_enable_npn); /* TLS NPN extension? */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
- BIT(connect_only);
#ifndef CURL_DISABLE_DOH
BIT(doh);
#endif
@@ -563,7 +580,7 @@ struct Curl_async {
struct Curl_dns_entry *dns;
struct thread_data *tdata;
void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+ ares_channel e.g. */
int port;
int status; /* if done is TRUE, this is the status from the callback */
BIT(done); /* set TRUE when the lookup is complete */
@@ -584,8 +601,9 @@ enum expect100 {
enum upgrade101 {
UPGR101_INIT, /* default state */
- UPGR101_REQUESTED, /* upgrade requested */
- UPGR101_RECEIVED, /* response received */
+ UPGR101_WS, /* upgrade to WebSockets requested */
+ UPGR101_H2, /* upgrade to HTTP/2 requested */
+ UPGR101_RECEIVED, /* 101 response received */
UPGR101_WORKING /* talking upgraded protocol */
};
@@ -607,23 +625,6 @@ enum doh_slots {
DOH_PROBE_SLOTS
};
-/* one of these for each DoH request */
-struct dnsprobe {
- CURL *easy;
- int dnstype;
- unsigned char dohbuffer[512];
- size_t dohlen;
- struct dynbuf serverdoh;
-};
-
-struct dohdata {
- struct curl_slist *headers;
- struct dnsprobe probe[DOH_PROBE_SLOTS];
- unsigned int pending; /* still outstanding requests */
- int port;
- const char *host;
-};
-
/*
* Request specific data in the easy handle (Curl_easy). Previously,
* these members were on the connectdata struct but since a conn struct may
@@ -707,6 +708,7 @@ struct SingleRequest {
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
+ unsigned char setcookies;
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
@@ -804,10 +806,10 @@ struct Curl_handler {
void (*attach)(struct Curl_easy *data, struct connectdata *conn);
int defport; /* Default port. */
- unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
- specific protocol bit */
- unsigned int family; /* single bit for protocol family; basically the
- non-TLS name of the protocol this is */
+ curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single
+ specific protocol bit */
+ curl_prot_t family; /* single bit for protocol family; basically the
+ non-TLS name of the protocol this is */
unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
};
@@ -828,7 +830,7 @@ struct Curl_handler {
url query strings (?foo=bar) ! */
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
-#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
+#define PROTOPT_ALPN (1<<8) /* set ALPN for this */
#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field
of the URL */
@@ -864,7 +866,8 @@ struct postponed_data {
struct proxy_info {
struct hostname host;
long port;
- curl_proxytype proxytype; /* what kind of proxy that is in use */
+ unsigned char proxytype; /* curl_proxytype: what kind of proxy that is in
+ use */
char *user; /* proxy user name string, allocated */
char *passwd; /* proxy password string, allocated */
};
@@ -903,6 +906,11 @@ struct connstate {
unsigned char *outp; /* send from this pointer */
};
+#define TRNSPRT_TCP 3
+#define TRNSPRT_UDP 4
+#define TRNSPRT_QUIC 5
+#define TRNSPRT_UNIX 6
+
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
@@ -940,15 +948,6 @@ struct connectdata {
cache entry remains locked. It gets unlocked in multi_done() */
struct Curl_addrinfo *ip_addr;
struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
-#ifdef ENABLE_IPV6
- unsigned int scope_id; /* Scope id for IPv6 */
-#endif
-
- enum {
- TRNSPRT_TCP = 3,
- TRNSPRT_UDP = 4,
- TRNSPRT_QUIC = 5
- } transport;
#ifdef ENABLE_QUIC
struct quicsocket hequic[2]; /* two, for happy eyeballs! */
@@ -964,13 +963,6 @@ struct connectdata {
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
#endif
- int port; /* which port to use locally - to connect to */
- int remote_port; /* the remote port, not the proxy port! */
- int conn_to_port; /* the remote port to connect to. valid only if
- bits.conn_to_port is set */
- unsigned short secondary_port; /* secondary socket remote port to connect to
- (ftp) */
-
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
ip address and port number whenever an outgoing connection is
*attempted* from the primary socket to a remote address. When more
@@ -979,14 +971,11 @@ struct connectdata {
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
- unsigned char ip_version; /* copied from the Curl_easy at creation time */
-
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *sasl_authzid; /* authorization identity string, allocated */
char *oauth_bearer; /* OAUTH2 bearer, allocated */
- unsigned char httpversion; /* the HTTP version*10 reported by the server */
struct curltime now; /* "current" time */
struct curltime created; /* creation time */
struct curltime lastused; /* when returned to the connection cache */
@@ -1013,8 +1002,6 @@ struct connectdata {
#endif
struct ConnectBits bits; /* various state-flags for this connection */
- /* The field below gets set in Curl_connecthost */
- int num_addr; /* number of addresses to try to connect to */
/* connecttime: when connect() is called on the current IP address. Used to
be able to track when to move on to try next IP - but only when the multi
interface is used. */
@@ -1042,9 +1029,9 @@ struct connectdata {
#ifdef HAVE_GSSAPI
BIT(sec_complete); /* if Kerberos is enabled for this connection */
- enum protection_level command_prot;
- enum protection_level data_prot;
- enum protection_level request_data_prot;
+ unsigned char command_prot; /* enum protection_level */
+ unsigned char data_prot; /* enum protection_level */
+ unsigned char request_data_prot; /* enum protection_level */
size_t buffer_size;
struct krb5buffer in_buffer;
void *app_data;
@@ -1091,18 +1078,38 @@ struct connectdata {
struct dynbuf trailer;
union {
+#ifndef CURL_DISABLE_FTP
struct ftp_conn ftpc;
+#endif
+#ifndef CURL_DISABLE_HTTP
struct http_conn httpc;
+#endif
+#ifdef USE_SSH
struct ssh_conn sshc;
+#endif
+#ifndef CURL_DISABLE_TFTP
struct tftp_state_data *tftpc;
+#endif
+#ifndef CURL_DISABLE_IMAP
struct imap_conn imapc;
+#endif
+#ifndef CURL_DISABLE_POP3
struct pop3_conn pop3c;
+#endif
+#ifndef CURL_DISABLE_SMTP
struct smtp_conn smtpc;
+#endif
+#ifndef CURL_DISABLE_RTSP
struct rtsp_conn rtspc;
+#endif
+#ifndef CURL_DISABLE_SMB
struct smb_conn smbc;
+#endif
void *rtmp;
struct ldapconninfo *ldapc;
+#ifndef CURL_DISABLE_MQTT
struct mqtt_conn mqtt;
+#endif
} proto;
struct http_connect_state *connect_state; /* for HTTP CONNECT */
@@ -1123,12 +1130,27 @@ struct connectdata {
int localportrange;
int cselect_bits; /* bitmask of socket events */
int waitfor; /* current READ/WRITE bits to wait for */
- int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
-
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
int socks5_gssapi_enctype;
#endif
+ /* The field below gets set in Curl_connecthost */
+ int num_addr; /* number of addresses to try to connect to */
+ int port; /* which port to use locally - to connect to */
+ int remote_port; /* the remote port, not the proxy port! */
+ int conn_to_port; /* the remote port to connect to. valid only if
+ bits.conn_to_port is set */
+#ifdef ENABLE_IPV6
+ unsigned int scope_id; /* Scope id for IPv6 */
+#endif
unsigned short localport;
+ unsigned short secondary_port; /* secondary socket remote port to connect to
+ (ftp) */
+ unsigned char alpn; /* APLN TLS negotiated protocol, a CURL_HTTP_VERSION*
+ value */
+ unsigned char transport; /* one of the TRNSPRT_* defines */
+ unsigned char ip_version; /* copied from the Curl_easy at creation time */
+ unsigned char httpversion; /* the HTTP version*10 reported by the server */
+ unsigned char connect_only;
};
/* The end of connectdata. */
@@ -1288,6 +1310,7 @@ typedef enum {
EXPIRE_TIMEOUT,
EXPIRE_TOOFAST,
EXPIRE_QUIC,
+ EXPIRE_FTP_ACCEPT,
EXPIRE_LAST /* not an actual timer, used as a marker only */
} expire_id;
@@ -1341,7 +1364,7 @@ struct UrlState {
This is strdup()ed data. */
char *first_host;
int first_remote_port;
- unsigned int first_remote_protocol;
+ curl_prot_t first_remote_protocol;
int retrycount; /* number of retries on a new connection */
struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
@@ -1356,9 +1379,10 @@ struct UrlState {
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
struct digestdata digest; /* state data for host Digest auth */
struct digestdata proxydigest; /* state data for proxy Digest auth */
-
+#endif
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
#ifdef USE_CURL_ASYNC
@@ -1374,7 +1398,7 @@ struct UrlState {
struct Curl_llist timeoutlist; /* list of pending timeouts */
struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
- /* a place to store the most recently set FTP entrypath */
+ /* a place to store the most recently set (S)FTP entrypath */
char *most_recent_ftp_entrypath;
unsigned char httpwant; /* when non-zero, a specific HTTP version requested
to be used in the library's request(s) */
@@ -1393,30 +1417,37 @@ struct UrlState {
this syntax. */
curl_off_t resume_from; /* continue [ftp] transfer from here */
+#ifndef CURL_DISABLE_RTSP
/* This RTSP state information survives requests and connections */
long rtsp_next_client_CSeq; /* the session's next client CSeq */
long rtsp_next_server_CSeq; /* the session's next server CSeq */
long rtsp_CSeq_recv; /* most recent CSeq received */
+#endif
curl_off_t infilesize; /* size of file to upload, -1 means unknown.
Copied from set.filesize at start of operation */
-
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
size_t drain; /* Increased when this stream has data to read, even if its
socket is not necessarily is readable. Decreased when
checked. */
+#endif
curl_read_callback fread_func; /* read callback/function */
void *in; /* CURLOPT_READDATA */
-
+#ifdef USE_HTTP2
struct Curl_easy *stream_depends_on;
int stream_weight;
+#endif
CURLU *uh; /* URL handle for the current parsed URL */
struct urlpieces up;
- Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
+ unsigned char httpreq; /* Curl_HttpReq; what kind of HTTP request (if any)
+ is this */
char *url; /* work URL, copied from UserDefined */
char *referer; /* referer string */
+#ifndef CURL_DISABLE_COOKIES
struct curl_slist *cookielist; /* list of cookie files set by
curl_easy_setopt(COOKIEFILE) calls */
+#endif
struct curl_slist *resolve; /* set to point to the set.resolve list when
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
@@ -1425,9 +1456,10 @@ struct UrlState {
headers */
struct Curl_llist httphdrs; /* received headers */
struct curl_header headerout; /* for external purposes */
-#endif
+ struct Curl_header_store *prevhead; /* the latest added header */
trailers_state trailers_state; /* whether we are sending trailers
- and what stage are we at */
+ and what stage are we at */
+#endif
#ifdef USE_HYPER
bool hconnect; /* set if a CONNECT request */
CURLcode hresult; /* used to pass return codes back from hyper callbacks */
@@ -1471,7 +1503,6 @@ struct UrlState {
is always set TRUE when curl_easy_perform() is called. */
BIT(authproblem); /* TRUE if there's some problem authenticating */
/* set after initial USER failure, to prevent an authentication loop */
- BIT(ftp_trying_alternative);
BIT(wildcardmatch); /* enable wildcard matching */
BIT(expect100header); /* TRUE if we added Expect: 100-continue */
BIT(disableexpect); /* TRUE if Expect: is disabled due to a previous
@@ -1548,8 +1579,6 @@ enum dupstring {
STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */
STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
- STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
- STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
STRING_SSL_CRLFILE, /* crl file to check certificate */
STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
@@ -1632,16 +1661,15 @@ struct UserDefined {
void *out; /* CURLOPT_WRITEDATA */
void *in_set; /* CURLOPT_READDATA */
void *writeheader; /* write the header to this if non-NULL */
- void *rtp_out; /* write RTP to this if non-NULL */
- long use_port; /* which port to use (when not using default) */
+ unsigned short use_port; /* which port to use (when not using default) */
unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
+#ifndef CURL_DISABLE_PROXY
unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */
+#endif
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
- int keep_post; /* keep POSTs as POSTs after a 30x request; each
- bit represents a request, from 301 to 303 */
void *postfields; /* if POST, set the fields' values here */
curl_seek_callback seek_func; /* function that seeks the input */
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
@@ -1679,16 +1707,17 @@ struct UserDefined {
#endif
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
- long timeout; /* in milliseconds, 0 means no timeout */
- long connecttimeout; /* in milliseconds, 0 means no timeout */
- long accepttimeout; /* in milliseconds, 0 means no timeout */
- long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
- long server_response_timeout; /* in milliseconds, 0 means no timeout */
+ unsigned int timeout; /* ms, 0 means no timeout */
+ unsigned int connecttimeout; /* ms, 0 means no timeout */
+ unsigned int happy_eyeballs_timeout; /* ms, 0 is a valid value */
+ unsigned int server_response_timeout; /* ms, 0 means no timeout */
long maxage_conn; /* in seconds, max idle time to allow a connection that
is to be reused */
long maxlifetime_conn; /* in seconds, max time since creation to allow a
connection that is to be reused */
+#ifndef CURL_DISABLE_TFTP
long tftp_blksize; /* in bytes, 0 means use default */
+#endif
curl_off_t filesize; /* size of file to upload, -1 means unknown */
long low_speed_limit; /* bytes/second */
long low_speed_time; /* number of seconds */
@@ -1708,15 +1737,17 @@ struct UserDefined {
the transfer on source host */
struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
the transfer on source host */
+#ifndef CURL_DISABLE_TELNET
struct curl_slist *telnet_options; /* linked list of telnet options */
+#endif
struct curl_slist *resolve; /* list of names to add/remove from
DNS cache */
struct curl_slist *connect_to; /* list of host:port mappings to override
the hostname and port to connect to */
- curl_TimeCond timecondition; /* kind of time/date comparison */
- curl_proxytype proxytype; /* what kind of proxy that is in use */
time_t timevalue; /* what time to compare with */
- Curl_HttpReq method; /* what kind of HTTP request (if any) is this */
+ unsigned char timecondition; /* kind of time comparison: curl_TimeCond */
+ unsigned char proxytype; /* what kind of proxy: curl_proxytype */
+ unsigned char method; /* what kind of HTTP request: Curl_HttpReq */
unsigned char httpwant; /* when non-zero, a specific HTTP version requested
to be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
@@ -1724,8 +1755,8 @@ struct UserDefined {
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
- long dns_cache_timeout; /* DNS cache timeout */
- long buffer_size; /* size of receive buffer to use */
+ int dns_cache_timeout; /* DNS cache timeout (seconds) */
+ unsigned int buffer_size; /* size of receive buffer to use */
unsigned int upload_buffer_size; /* size of upload buffer to use,
keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
@@ -1734,36 +1765,46 @@ struct UserDefined {
file 0 - whatever, 1 - v2, 2 - v6 */
curl_off_t max_filesize; /* Maximum file size to download */
#ifndef CURL_DISABLE_FTP
- curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
- curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
- curl_ftpccc ftp_ccc; /* FTP CCC options */
+ unsigned char ftp_filemethod; /* how to get to a file: curl_ftpfile */
+ unsigned char ftpsslauth; /* what AUTH XXX to try: curl_ftpauth */
+ unsigned char ftp_ccc; /* FTP CCC options: curl_ftpccc */
+ unsigned int accepttimeout; /* in milliseconds, 0 means no timeout */
+#endif
+ /* Desppie the name ftp_create_missing_dirs is for FTP(S) and SFTP
+ 1 - create directories that don't exist
+ 2 - the same but also allow MKD to fail once
+ */
+ unsigned char ftp_create_missing_dirs;
+#ifdef USE_LIBSSH2
+ curl_sshhostkeycallback ssh_hostkeyfunc; /* hostkey check callback */
+ void *ssh_hostkeyfunc_userp; /* custom pointer to callback */
#endif
- int ftp_create_missing_dirs; /* 1 - create directories that don't exist
- 2 - the same but also allow MKD to fail once
- */
+
curl_sshkeycallback ssh_keyfunc; /* key matching callback */
void *ssh_keyfunc_userp; /* custom pointer to callback */
#ifndef CURL_DISABLE_NETRC
- enum CURL_NETRC_OPTION
- use_netrc; /* defined in include/curl.h */
+ unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */
#endif
curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! */
- long new_file_perms; /* Permissions to use when creating remote files */
- long new_directory_perms; /* Permissions to use when creating remote dirs */
- long ssh_auth_types; /* allowed SSH auth types */
+ unsigned int new_file_perms; /* when creating remote files */
+ unsigned int new_directory_perms; /* when creating remote dirs */
+ int ssh_auth_types; /* allowed SSH auth types */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
struct curl_blob *blobs[BLOB_LAST];
#ifdef ENABLE_IPV6
unsigned int scope_id; /* Scope id for IPv6 */
#endif
- long allowed_protocols;
- long redir_protocols;
- long mime_options; /* Mime option flags. */
- struct curl_slist *mail_rcpt; /* linked list of mail recipients */
+ curl_prot_t allowed_protocols;
+ curl_prot_t redir_protocols;
+ unsigned int mime_options; /* Mime option flags. */
+
+#ifndef CURL_DISABLE_RTSP
+ void *rtp_out; /* write RTP to this if non-NULL */
/* Common RTSP header options */
Curl_RtspReq rtspreq; /* RTSP request type */
- long rtspversion; /* like httpversion, for RTSP */
+#endif
+#ifndef CURL_DISABLE_FTP
curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer
starts */
curl_chunk_end_callback chunk_end; /* called after part transferring
@@ -1771,38 +1812,48 @@ struct UserDefined {
curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds
to pattern (e.g. if WILDCARDMATCH is on) */
void *fnmatch_data;
-
+#endif
long gssapi_delegation; /* GSS-API credential delegation, see the
documentation of CURLOPT_GSSAPI_DELEGATION */
- long tcp_keepidle; /* seconds in idle before sending keepalive probe */
- long tcp_keepintvl; /* seconds between TCP keepalive probes */
+ int tcp_keepidle; /* seconds in idle before sending keepalive probe */
+ int tcp_keepintvl; /* seconds between TCP keepalive probes */
size_t maxconnects; /* Max idle connections in the connection cache */
long expect_100_timeout; /* in milliseconds */
+#ifdef USE_HTTP2
struct Curl_easy *stream_depends_on;
int stream_weight;
struct Curl_http2_dep *stream_dependents;
-
+#endif
curl_resolver_start_callback resolver_start; /* optional callback called
before resolver start */
void *resolver_start_client; /* pointer to pass to resolver start callback */
long upkeep_interval_ms; /* Time between calls for connection upkeep. */
multidone_func fmultidone;
+#ifndef CURL_DISABLE_DOH
struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
+#endif
CURLU *uh; /* URL handle for the current parsed URL */
void *trailer_data; /* pointer to pass to trailer data callback */
curl_trailer_callback trailer_callback; /* trailing data callback */
+ char keep_post; /* keep POSTs as POSTs after a 30x request; each
+ bit represents a request, from 301 to 303 */
+#ifndef CURL_DISABLE_SMTP
+ struct curl_slist *mail_rcpt; /* linked list of mail recipients */
+ BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
+ recipients */
+#endif
+ unsigned char connect_only; /* make connection/request, then let
+ application use the socket */
BIT(is_fread_set); /* has read callback been set to non-NULL? */
- BIT(is_fwrite_set); /* has write callback been set to non-NULL? */
- BIT(free_referer); /* set TRUE if 'referer' points to a string we
- allocated */
+#ifndef CURL_DISABLE_TFTP
BIT(tftp_no_options); /* do not send TFTP options requests */
+#endif
BIT(sep_headers); /* handle host and proxy headers separately */
BIT(cookiesession); /* new cookie session? */
BIT(crlf); /* convert crlf on ftp upload(?) */
- BIT(strip_path_slash); /* strip off initial slash from path */
BIT(ssh_compression); /* enable SSH compression */
/* Here follows boolean settings that define how to behave during
@@ -1820,6 +1871,7 @@ struct UserDefined {
BIT(ftp_use_pret); /* if PRET is to be used before PASV or not */
BIT(ftp_skip_ip); /* skip the IP address the FTP server passes on to
us */
+ BIT(wildcard_enabled); /* enable wildcard matching */
#endif
BIT(hide_progress); /* don't use the progress meter */
BIT(http_fail_on_error); /* fail on HTTP error codes >= 400 */
@@ -1840,7 +1892,6 @@ struct UserDefined {
BIT(no_signal); /* do not use any signal/alarm handler */
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
BIT(ignorecl); /* ignore content length */
- BIT(connect_only); /* make connection, let application use the socket */
BIT(http_te_skip); /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */
BIT(http_ce_skip); /* pass the raw body data to the user, even when
@@ -1851,10 +1902,8 @@ struct UserDefined {
BIT(socks5_gssapi_nec); /* Flag to support NEC SOCKS5 server */
#endif
BIT(sasl_ir); /* Enable/disable SASL initial response */
- BIT(wildcard_enabled); /* enable wildcard matching */
BIT(tcp_keepalive); /* use TCP keepalives */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(ssl_enable_npn); /* TLS NPN extension? */
BIT(ssl_enable_alpn);/* TLS ALPN extension? */
BIT(path_as_is); /* allow dotdots? */
BIT(pipewait); /* wait for multiplex status before starting a new
@@ -1874,8 +1923,9 @@ struct UserDefined {
BIT(doh_verifystatus); /* DoH certificate status verification */
#endif
BIT(http09_allowed); /* allow HTTP/0.9 responses */
- BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
- recipients */
+#ifdef USE_WEBSOCKETS
+ BIT(ws_raw_mode);
+#endif
};
struct Names {
@@ -1937,10 +1987,12 @@ struct Curl_easy {
#endif
struct SingleRequest req; /* Request-specific data */
struct UserDefined set; /* values set by the libcurl user */
+#ifndef CURL_DISABLE_COOKIES
struct CookieInfo *cookies; /* the cookies, read from files and servers.
NOTE that the 'cookie' field in the
UserDefined struct defines if the "engine"
is to be used or not. */
+#endif
#ifndef CURL_DISABLE_HSTS
struct hsts *hsts;
#endif
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index d17e16f10..b82b17146 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC4616 PLAIN authentication
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
*
diff --git a/Utilities/cmcurl/lib/vauth/cram.c b/Utilities/cmcurl/lib/vauth/cram.c
index 9ddb0ac37..475d31b8d 100644
--- a/Utilities/cmcurl/lib/vauth/cram.c
+++ b/Utilities/cmcurl/lib/vauth/cram.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2195 CRAM-MD5 authentication
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index d4616095d..f945e8b6c 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2831 DIGEST-MD5 authentication
* RFC7616 DIGEST-SHA256, DIGEST-SHA512-256 authentication
*
@@ -47,6 +49,15 @@
#include "curl_memory.h"
#include "memdebug.h"
+#define SESSION_ALGO 1 /* for algos with this bit set */
+
+#define ALGO_MD5 0
+#define ALGO_MD5SESS (ALGO_MD5 | SESSION_ALGO)
+#define ALGO_SHA256 2
+#define ALGO_SHA256SESS (ALGO_SHA256 | SESSION_ALGO)
+#define ALGO_SHA512_256 4
+#define ALGO_SHA512_256SESS (ALGO_SHA512_256 | SESSION_ALGO)
+
#if !defined(USE_WINDOWS_SSPI)
#define DIGEST_QOP_VALUE_AUTH (1 << 0)
#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
@@ -79,44 +90,50 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
}
for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) {
- switch(*str) {
- case '\\':
- if(!escape) {
- /* possibly the start of an escaped quote */
- escape = TRUE;
- *content++ = '\\'; /* Even though this is an escape character, we still
- store it as-is in the target buffer */
- continue;
- }
- break;
-
- case ',':
- if(!starts_with_quote) {
- /* This signals the end of the content if we didn't get a starting
- quote and then we do "sloppy" parsing */
- c = 0; /* the end */
- continue;
- }
- break;
-
- case '\r':
- case '\n':
- /* end of string */
- c = 0;
- continue;
+ if(!escape) {
+ switch(*str) {
+ case '\\':
+ if(starts_with_quote) {
+ /* the start of an escaped quote */
+ escape = TRUE;
+ continue;
+ }
+ break;
+
+ case ',':
+ if(!starts_with_quote) {
+ /* This signals the end of the content if we didn't get a starting
+ quote and then we do "sloppy" parsing */
+ c = 0; /* the end */
+ continue;
+ }
+ break;
- case '\"':
- if(!escape && starts_with_quote) {
+ case '\r':
+ case '\n':
/* end of string */
+ if(starts_with_quote)
+ return FALSE; /* No closing quote */
c = 0;
continue;
+
+ case '\"':
+ if(starts_with_quote) {
+ /* end of string */
+ c = 0;
+ continue;
+ }
+ else
+ return FALSE;
+ break;
}
- break;
}
escape = FALSE;
*content++ = *str;
}
+ if(escape)
+ return FALSE; /* No character after backslash */
*content = 0;
*endptr = str;
@@ -365,7 +382,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING;
- /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
+ /* Generate 32 random hex chars, 32 bytes + 1 null-termination */
result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result)
return result;
@@ -504,7 +521,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -543,6 +560,9 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
token = strtok_r(tmp, ",", &tok_buf);
while(token) {
+ /* Pass additional spaces here */
+ while(*token && ISBLANK(*token))
+ token++;
if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
foundAuth = TRUE;
}
@@ -575,17 +595,17 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
return CURLE_OUT_OF_MEMORY;
if(strcasecompare(content, "MD5-sess"))
- digest->algo = CURLDIGESTALGO_MD5SESS;
+ digest->algo = ALGO_MD5SESS;
else if(strcasecompare(content, "MD5"))
- digest->algo = CURLDIGESTALGO_MD5;
+ digest->algo = ALGO_MD5;
else if(strcasecompare(content, "SHA-256"))
- digest->algo = CURLDIGESTALGO_SHA256;
+ digest->algo = ALGO_SHA256;
else if(strcasecompare(content, "SHA-256-SESS"))
- digest->algo = CURLDIGESTALGO_SHA256SESS;
+ digest->algo = ALGO_SHA256SESS;
else if(strcasecompare(content, "SHA-512-256"))
- digest->algo = CURLDIGESTALGO_SHA512_256;
+ digest->algo = ALGO_SHA512_256;
else if(strcasecompare(content, "SHA-512-256-SESS"))
- digest->algo = CURLDIGESTALGO_SHA512_256SESS;
+ digest->algo = ALGO_SHA512_256SESS;
else
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -602,7 +622,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
@@ -620,6 +640,10 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
if(!digest->nonce)
return CURLE_BAD_CONTENT_ENCODING;
+ /* "<algo>-sess" protocol versions require "auth" or "auth-int" qop */
+ if(!digest->qop && (digest->algo & SESSION_ALGO))
+ return CURLE_BAD_CONTENT_ENCODING;
+
return CURLE_OK;
}
@@ -664,6 +688,8 @@ static CURLcode auth_create_digest_http_message(
char *cnonce = NULL;
size_t cnonce_sz = 0;
char *userp_quoted;
+ char *realm_quoted;
+ char *nonce_quoted;
char *response = NULL;
char *hashthis = NULL;
char *tmp = NULL;
@@ -687,7 +713,7 @@ static CURLcode auth_create_digest_http_message(
}
if(digest->userhash) {
- hashthis = aprintf("%s:%s", userp, digest->realm);
+ hashthis = aprintf("%s:%s", userp, digest->realm ? digest->realm : "");
if(!hashthis)
return CURLE_OUT_OF_MEMORY;
@@ -707,7 +733,8 @@ static CURLcode auth_create_digest_http_message(
unq(nonce-value) ":" unq(cnonce-value)
*/
- hashthis = aprintf("%s:%s:%s", userp, digest->realm, passwdp);
+ hashthis = aprintf("%s:%s:%s", userp, digest->realm ? digest->realm : "",
+ passwdp);
if(!hashthis)
return CURLE_OUT_OF_MEMORY;
@@ -715,9 +742,7 @@ static CURLcode auth_create_digest_http_message(
free(hashthis);
convert_to_ascii(hashbuf, ha1);
- if(digest->algo == CURLDIGESTALGO_MD5SESS ||
- digest->algo == CURLDIGESTALGO_SHA256SESS ||
- digest->algo == CURLDIGESTALGO_SHA512_256SESS) {
+ if(digest->algo & SESSION_ALGO) {
/* nonce and cnonce are OUTSIDE the hash */
tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
if(!tmp)
@@ -786,16 +811,33 @@ static CURLcode auth_create_digest_http_message(
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
Digest parameters are all quoted strings. Username which is provided by
- the user will need double quotes and backslashes within it escaped. For
- the other fields, this shouldn't be an issue. realm, nonce, and opaque
- are copied as is from the server, escapes and all. cnonce is generated
- with web-safe characters. uri is already percent encoded. nc is 8 hex
+ the user will need double quotes and backslashes within it escaped.
+ realm, nonce, and opaque will need backslashes as well as they were
+ de-escaped when copied from request header. cnonce is generated with
+ web-safe characters. uri is already percent encoded. nc is 8 hex
characters. algorithm and qop with standard values only contain web-safe
characters.
*/
userp_quoted = auth_digest_string_quoted(digest->userhash ? userh : userp);
if(!userp_quoted)
return CURLE_OUT_OF_MEMORY;
+ if(digest->realm)
+ realm_quoted = auth_digest_string_quoted(digest->realm);
+ else {
+ realm_quoted = malloc(1);
+ if(realm_quoted)
+ realm_quoted[0] = 0;
+ }
+ if(!realm_quoted) {
+ free(userp_quoted);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ nonce_quoted = auth_digest_string_quoted(digest->nonce);
+ if(!nonce_quoted) {
+ free(realm_quoted);
+ free(userp_quoted);
+ return CURLE_OUT_OF_MEMORY;
+ }
if(digest->qop) {
response = aprintf("username=\"%s\", "
@@ -807,18 +849,16 @@ static CURLcode auth_create_digest_http_message(
"qop=%s, "
"response=\"%s\"",
userp_quoted,
- digest->realm,
- digest->nonce,
+ realm_quoted,
+ nonce_quoted,
uripath,
digest->cnonce,
digest->nc,
digest->qop,
request_digest);
- if(strcasecompare(digest->qop, "auth"))
- digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
- padded which tells to the server how many times you are
- using the same nonce in the qop=auth mode */
+ /* Increment nonce-count to use another nc value for the next request */
+ digest->nc++;
}
else {
response = aprintf("username=\"%s\", "
@@ -827,20 +867,29 @@ static CURLcode auth_create_digest_http_message(
"uri=\"%s\", "
"response=\"%s\"",
userp_quoted,
- digest->realm,
- digest->nonce,
+ realm_quoted,
+ nonce_quoted,
uripath,
request_digest);
}
+ free(nonce_quoted);
+ free(realm_quoted);
free(userp_quoted);
if(!response)
return CURLE_OUT_OF_MEMORY;
/* Add the optional fields */
if(digest->opaque) {
+ char *opaque_quoted;
/* Append the opaque */
- tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque);
+ opaque_quoted = auth_digest_string_quoted(digest->opaque);
+ if(!opaque_quoted) {
+ free(response);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ tmp = aprintf("%s, opaque=\"%s\"", response, opaque_quoted);
free(response);
+ free(opaque_quoted);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
@@ -902,28 +951,18 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
struct digestdata *digest,
char **outptr, size_t *outlen)
{
- switch(digest->algo) {
- case CURLDIGESTALGO_MD5:
- case CURLDIGESTALGO_MD5SESS:
+ if(digest->algo <= ALGO_MD5SESS)
return auth_create_digest_http_message(data, userp, passwdp,
request, uripath, digest,
outptr, outlen,
auth_digest_md5_to_ascii,
Curl_md5it);
-
- case CURLDIGESTALGO_SHA256:
- case CURLDIGESTALGO_SHA256SESS:
- case CURLDIGESTALGO_SHA512_256:
- case CURLDIGESTALGO_SHA512_256SESS:
- return auth_create_digest_http_message(data, userp, passwdp,
- request, uripath, digest,
- outptr, outlen,
- auth_digest_sha256_to_ascii,
- Curl_sha256it);
-
- default:
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
+ DEBUGASSERT(digest->algo <= ALGO_SHA512_256SESS);
+ return auth_create_digest_http_message(data, userp, passwdp,
+ request, uripath, digest,
+ outptr, outlen,
+ auth_digest_sha256_to_ascii,
+ Curl_sha256it);
}
/*
@@ -946,7 +985,7 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
Curl_safefree(digest->algorithm);
digest->nc = 0;
- digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */
+ digest->algo = ALGO_MD5; /* default algorithm */
digest->stale = FALSE; /* default means normal, not stale */
digest->userhash = FALSE;
}
diff --git a/Utilities/cmcurl/lib/vauth/digest.h b/Utilities/cmcurl/lib/vauth/digest.h
index ee373cd82..d785bdd91 100644
--- a/Utilities/cmcurl/lib/vauth/digest.h
+++ b/Utilities/cmcurl/lib/vauth/digest.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
@@ -29,15 +31,6 @@
#define DIGEST_MAX_VALUE_LENGTH 256
#define DIGEST_MAX_CONTENT_LENGTH 1024
-enum {
- CURLDIGESTALGO_MD5,
- CURLDIGESTALGO_MD5SESS,
- CURLDIGESTALGO_SHA256,
- CURLDIGESTALGO_SHA256SESS,
- CURLDIGESTALGO_SHA512_256,
- CURLDIGESTALGO_SHA512_256SESS
-};
-
/* This is used to extract the realm from a challenge message */
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
const char **endptr);
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 94f8f8c0d..89a9db52c 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC2831 DIGEST-MD5 authentication
*
***************************************************************************/
@@ -257,7 +259,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -290,7 +292,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
@@ -331,7 +333,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
char value[DIGEST_MAX_VALUE_LENGTH];
char content[DIGEST_MAX_CONTENT_LENGTH];
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(!Curl_auth_digest_get_pair(p, value, content, &p))
@@ -343,7 +345,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
break;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(',' == *p)
@@ -429,8 +431,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
has changed then delete that context. */
if((userp && !digest->user) || (!userp && digest->user) ||
(passwdp && !digest->passwd) || (!passwdp && digest->passwd) ||
- (userp && digest->user && strcmp(userp, digest->user)) ||
- (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) {
+ (userp && digest->user && Curl_timestrcmp(userp, digest->user)) ||
+ (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) {
if(digest->http_context) {
s_pSecFn->DeleteSecurityContext(digest->http_context);
Curl_safefree(digest->http_context);
diff --git a/Utilities/cmcurl/lib/vauth/gsasl.c b/Utilities/cmcurl/lib/vauth/gsasl.c
index 40fef53c9..a73c64443 100644
--- a/Utilities/cmcurl/lib/vauth/gsasl.c
+++ b/Utilities/cmcurl/lib/vauth/gsasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2021, Simon Josefsson, <simon@josefsson.org>, et al.
+ * Copyright (C) 2020 - 2022, Simon Josefsson, <simon@josefsson.org>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC5802 SCRAM-SHA-1 authentication
*
***************************************************************************/
@@ -34,7 +36,8 @@
#include <gsasl.h>
-/* The last #include files should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index 67d43bd56..bac78049d 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index c652fd736..895b4a193 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2021, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index 115f70b0e..c10fa6caa 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -27,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -62,6 +64,10 @@
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
+/* The fixed host name we provide, in order to not leak our real local host
+ name. Copy the name used by Firefox. */
+#define NTLM_HOSTNAME "WORKSTATION"
+
#if DEBUG_ME
# define DEBUG_OUT(x) x
static void ntlm_print_flags(FILE *handle, unsigned long flags)
@@ -521,6 +527,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
userlen = strlen(user);
+#ifndef NTLM_HOSTNAME
/* Get the machine's un-qualified host name as NTLM doesn't like the fully
qualified domain name */
if(Curl_gethostname(host, sizeof(host))) {
@@ -530,6 +537,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
else {
hostlen = strlen(host);
}
+#else
+ (void)msnprintf(host, sizeof(host), "%s", NTLM_HOSTNAME);
+ hostlen = sizeof(NTLM_HOSTNAME)-1;
+#endif
if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
unsigned char ntbuffer[0x18];
@@ -589,7 +600,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* A safer but less compatible alternative is:
* Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
- * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
+ * See https://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
}
if(unicode) {
@@ -647,7 +658,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* LanManager response */
/* NT response */
- 0, /* zero termination */
+ 0, /* null-termination */
0, 0, 0, /* type-3 long, the 24 upper bits */
SHORTPAIR(0x18), /* LanManager response length, twice */
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index 8ec23ad4f..4dfda5545 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -32,7 +34,8 @@
/* Stuff only required for curl_ntlm_msgs.c */
#ifdef BUILDING_CURL_NTLM_MSGS_C
-/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */
+/* Flag bits definitions based on
+ https://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 3e39dad31..193576aca 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vauth/oauth2.c b/Utilities/cmcurl/lib/vauth/oauth2.c
index a5f16a0bf..1604b303e 100644
--- a/Utilities/cmcurl/lib/vauth/oauth2.c
+++ b/Utilities/cmcurl/lib/vauth/oauth2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC6749 OAuth 2.0 Authorization Framework
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
index 8c1a3edd0..25dff967d 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC4178 Simple and Protected GSS-API Negotiation Mechanism
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index d219d8bb2..d845caca6 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
* RFC4178 Simple and Protected GSS-API Negotiation Mechanism
*
***************************************************************************/
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index 3624fb0c4..58fe05139 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2021, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -25,6 +27,8 @@
#include <curl/curl.h>
#include "vauth.h"
+#include "urldata.h"
+#include "strcase.h"
#include "curl_multibyte.h"
#include "curl_printf.h"
@@ -142,3 +146,18 @@ bool Curl_auth_user_contains_domain(const char *user)
return valid;
}
+
+/*
+ * Curl_auth_ollowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ return (!data->state.this_is_a_follow ||
+ data->set.allow_auth_to_other_hosts ||
+ (data->state.first_host &&
+ strcasecompare(data->state.first_host, conn->host.name) &&
+ (data->state.first_remote_port == conn->remote_port) &&
+ (data->state.first_remote_protocol == conn->handler->protocol)));
+}
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index 6e1237834..af27f01df 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
@@ -52,6 +54,12 @@ struct gsasldata;
#define GSS_ERROR(status) ((status) & 0x80000000)
#endif
+/*
+ * Curl_auth_allowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data);
+
/* This is used to build a SPN string */
#if !defined(USE_WINDOWS_SSPI)
char *Curl_auth_build_spn(const char *service, const char *host,
@@ -222,7 +230,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego,
char **outptr, size_t *outlen);
-/* This is used to clean up the SPNEGO specifiec data */
+/* This is used to clean up the SPNEGO specific data */
void Curl_auth_cleanup_spnego(struct negotiatedata *nego);
#endif /* USE_SPNEGO */
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index e37253df2..cb44eb406 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -29,6 +31,7 @@
#include "vssh/ssh.h"
#include "quic.h"
#include "curl_printf.h"
+#include "easy_lock.h"
#ifdef USE_ARES
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
@@ -50,8 +53,8 @@
#include <librtmp/rtmp.h>
#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
+#ifdef HAVE_LIBZ
+#include <cm3p/zlib.h>
#endif
#ifdef HAVE_BROTLI
@@ -335,6 +338,11 @@ static const char * const protocols[] = {
#endif
#ifdef USE_LIBRTMP
"rtmp",
+ "rtmpe",
+ "rtmps",
+ "rtmpt",
+ "rtmpte",
+ "rtmpts",
#endif
#ifndef CURL_DISABLE_RTSP
"rtsp",
@@ -364,6 +372,12 @@ static const char * const protocols[] = {
#ifndef CURL_DISABLE_TFTP
"tftp",
#endif
+#ifdef USE_WEBSOCKETS
+ "ws",
+#endif
+#if defined(USE_SSL) && defined(USE_WEBSOCKETS)
+ "wss",
+#endif
NULL
};
@@ -451,6 +465,9 @@ static curl_version_info_data version_info = {
#if defined(USE_GSASL)
| CURL_VERSION_GSASL
#endif
+#if defined(GLOBAL_INIT_IS_THREADSAFE)
+ | CURL_VERSION_THREADSAFE
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
diff --git a/Utilities/cmcurl/lib/version_win32.c b/Utilities/cmcurl/lib/version_win32.c
index afdb1d6a7..e8f14f9df 100644
--- a/Utilities/cmcurl/lib/version_win32.c
+++ b/Utilities/cmcurl/lib/version_win32.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/version_win32.h b/Utilities/cmcurl/lib/version_win32.h
index 38af87fa0..7a9a6a14f 100644
--- a/Utilities/cmcurl/lib/version_win32.h
+++ b/Utilities/cmcurl/lib/version_win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2021, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vquic/msh3.c b/Utilities/cmcurl/lib/vquic/msh3.c
index f7bd315be..c3e58e726 100644
--- a/Utilities/cmcurl/lib/vquic/msh3.c
+++ b/Utilities/cmcurl/lib/vquic/msh3.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -25,7 +27,6 @@
#ifdef USE_MSH3
#include "urldata.h"
-#include "curl_printf.h"
#include "timeval.h"
#include "multiif.h"
#include "sendf.h"
@@ -33,6 +34,11 @@
#include "h2h3.h"
#include "msh3.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
/* #define DEBUG_HTTP3 1 */
#ifdef DEBUG_HTTP3
#define H3BUGF(x) x
@@ -108,7 +114,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
socklen_t addrlen)
{
struct quicsocket *qs = &conn->hequic[sockindex];
- bool unsecure = !conn->ssl_config.verifypeer;
+ bool insecure = !conn->ssl_config.verifypeer;
memset(qs, 0, sizeof(*qs));
(void)sockfd;
@@ -126,7 +132,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
qs->conn = MsH3ConnectionOpen(qs->api,
conn->host.name,
(uint16_t)conn->remote_port,
- unsecure);
+ insecure);
if(!qs->conn) {
failf(data, "can't create msh3 connection");
if(qs->api) {
@@ -220,13 +226,8 @@ static unsigned int msh3_conncheck(struct Curl_easy *data,
return CONNRESULT_NONE;
}
-static void msh3_cleanup(struct quicsocket *qs, struct HTTP *stream)
+static void disconnect(struct quicsocket *qs)
{
- if(stream && stream->recv_buf) {
- free(stream->recv_buf);
- stream->recv_buf = ZERO_NULL;
- msh3_lock_uninitialize(&stream->recv_lock);
- }
if(qs->conn) {
MsH3ConnectionClose(qs->conn);
qs->conn = ZERO_NULL;
@@ -240,18 +241,20 @@ static void msh3_cleanup(struct quicsocket *qs, struct HTTP *stream)
static CURLcode msh3_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
+ (void)data;
(void)dead_connection;
H3BUGF(infof(data, "disconnecting (msh3)"));
- msh3_cleanup(conn->quic, data->req.p.http);
+ disconnect(conn->quic);
return CURLE_OK;
}
void Curl_quic_disconnect(struct Curl_easy *data, struct connectdata *conn,
int tempindex)
{
+ (void)data;
if(conn->transport == TRNSPRT_QUIC) {
- H3BUGF(infof(data, "disconnecting (curl)"));
- msh3_cleanup(&conn->hequic[tempindex], data->req.p.http);
+ H3BUGF(infof(data, "disconnecting QUIC index %u", tempindex));
+ disconnect(&conn->hequic[tempindex]);
}
}
@@ -286,7 +289,6 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
struct HTTP *stream = IfContext;
size_t total_len;
(void)Request;
- H3BUGF(printf("* msh3_header_received\n"));
if(stream->recv_header_complete) {
H3BUGF(printf("* ignoring header after data\n"));
@@ -379,9 +381,6 @@ static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext)
(void)stream;
}
-static_assert(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo),
- "Sizes must match for cast below to work");
-
static ssize_t msh3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
@@ -394,6 +393,9 @@ static ssize_t msh3_stream_send(struct Curl_easy *data,
struct h2h3req *hreq;
(void)sockindex;
+ /* Sizes must match for cast below to work" */
+ DEBUGASSERT(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo));
+
H3BUGF(infof(data, "msh3_stream_send %zu", len));
if(!stream->req) {
@@ -488,9 +490,19 @@ CURLcode Curl_quic_done_sending(struct Curl_easy *data)
void Curl_quic_done(struct Curl_easy *data, bool premature)
{
- (void)data;
+ struct HTTP *stream = data->req.p.http;
(void)premature;
H3BUGF(infof(data, "Curl_quic_done"));
+ if(stream) {
+ if(stream->recv_buf) {
+ Curl_safefree(stream->recv_buf);
+ msh3_lock_uninitialize(&stream->recv_lock);
+ }
+ if(stream->req) {
+ MsH3RequestClose(stream->req);
+ stream->req = ZERO_NULL;
+ }
+ }
}
bool Curl_quic_data_pending(const struct Curl_easy *data)
@@ -500,4 +512,16 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
return stream->recv_header_len || stream->recv_data_len;
}
+/*
+ * Called from transfer.c:Curl_readwrite when neither HTTP level read
+ * nor write is performed. It is a good place to handle timer expiry
+ * for QUIC transport.
+ */
+CURLcode Curl_quic_idle(struct Curl_easy *data)
+{
+ (void)data;
+ H3BUGF(infof(data, "Curl_quic_idle"));
+ return CURLE_OK;
+}
+
#endif /* USE_MSH3 */
diff --git a/Utilities/cmcurl/lib/vquic/msh3.h b/Utilities/cmcurl/lib/vquic/msh3.h
index bacdcb132..ce884d92d 100644
--- a/Utilities/cmcurl/lib/vquic/msh3.h
+++ b/Utilities/cmcurl/lib/vquic/msh3.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index f1a64eea8..097cca44b 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -18,21 +18,29 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGTCP2
#include <ngtcp2/ngtcp2.h>
-#include <ngtcp2/ngtcp2_crypto.h>
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/err.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <ngtcp2/ngtcp2_crypto_boringssl.h>
+#else
#include <ngtcp2/ngtcp2_crypto_openssl.h>
+#endif
#include "vtls/openssl.h"
#elif defined(USE_GNUTLS)
#include <ngtcp2/ngtcp2_crypto_gnutls.h>
#include "vtls/gtls.h"
+#elif defined(USE_WOLFSSL)
+#include <ngtcp2/ngtcp2_crypto_wolfssl.h>
+#include "vtls/wolfssl.h"
#endif
#include "urldata.h"
#include "sendf.h"
@@ -96,17 +104,32 @@ struct h3out {
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
"%DISABLE_TLS13_COMPAT_MODE"
+#elif defined(USE_WOLFSSL)
+#define QUIC_CIPHERS \
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
+ "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:P-384:P-521"
#endif
+/* ngtcp2 default congestion controller does not perform pacing. Limit
+ the maximum packet burst to MAX_PKT_BURST packets. */
+#define MAX_PKT_BURST 10
+
static CURLcode ng_process_ingress(struct Curl_easy *data,
curl_socket_t sockfd,
struct quicsocket *qs);
static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
- size_t datalen, void *user_data,
+ uint64_t datalen, void *user_data,
void *stream_user_data);
+static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref)
+{
+ struct quicsocket *qs = conn_ref->user_data;
+ return qs->qconn;
+}
+
static ngtcp2_tstamp timestamp(void)
{
struct curltime ct = Curl_now();
@@ -187,91 +210,44 @@ static int keylog_callback(gnutls_session_t session, const char *label,
Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
return 0;
}
-#endif
-
-static int init_ngh3_conn(struct quicsocket *qs);
-
-static int write_client_handshake(struct quicsocket *qs,
- ngtcp2_crypto_level level,
- const uint8_t *data, size_t len)
-{
- int rv;
-
- rv = ngtcp2_conn_submit_crypto_data(qs->qconn, level, data, len);
- if(rv) {
- H3BUGF(fprintf(stderr, "write_client_handshake failed\n"));
- }
- assert(0 == rv);
-
- return 1;
-}
-
-#ifdef USE_OPENSSL
-static int quic_set_encryption_secrets(SSL *ssl,
- OSSL_ENCRYPTION_LEVEL ossl_level,
- const uint8_t *rx_secret,
- const uint8_t *tx_secret,
- size_t secretlen)
-{
- struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- int level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
-
- if(ngtcp2_crypto_derive_and_install_rx_key(
- qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
- return 0;
-
- if(ngtcp2_crypto_derive_and_install_tx_key(
- qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
- return 0;
-
- if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
- if(init_ngh3_conn(qs) != CURLE_OK)
- return 0;
- }
-
- return 1;
-}
-
-static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
- const uint8_t *data, size_t len)
-{
- struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- ngtcp2_crypto_level level =
- ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
-
- return write_client_handshake(qs, level, data, len);
-}
-
-static int quic_flush_flight(SSL *ssl)
+#elif defined(USE_WOLFSSL)
+#if defined(HAVE_SECRET_CALLBACK)
+static void keylog_callback(const WOLFSSL *ssl, const char *line)
{
(void)ssl;
- return 1;
-}
-
-static int quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level,
- uint8_t alert)
-{
- struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- (void)level;
-
- qs->tls_alert = alert;
- return 1;
+ Curl_tls_keylog_write_line(line);
}
+#endif
+#endif
-static SSL_QUIC_METHOD quic_method = {quic_set_encryption_secrets,
- quic_add_handshake_data,
- quic_flush_flight, quic_send_alert};
+static int init_ngh3_conn(struct quicsocket *qs);
+#ifdef USE_OPENSSL
static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
- SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
- SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
+#ifdef OPENSSL_IS_BORINGSSL
+ if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
+ return NULL;
+ }
+#else
+ if(ngtcp2_crypto_openssl_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_openssl_configure_client_context failed");
+ return NULL;
+ }
+#endif
SSL_CTX_set_default_verify_paths(ssl_ctx);
+#ifdef OPENSSL_IS_BORINGSSL
+ if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
+ failf(data, "SSL_CTX_set1_curves_list failed");
+ return NULL;
+ }
+#else
if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
@@ -283,8 +259,7 @@ static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
failf(data, "SSL_CTX_set1_groups_list failed");
return NULL;
}
-
- SSL_CTX_set_quic_method(ssl_ctx, &quic_method);
+#endif
/* Open the file if a TLS or QUIC backend has not done this before. */
Curl_tls_keylog_open();
@@ -353,7 +328,7 @@ static int quic_init_ssl(struct quicsocket *qs)
DEBUGASSERT(!qs->ssl);
qs->ssl = SSL_new(qs->sslctx);
- SSL_set_app_data(qs->ssl, qs);
+ SSL_set_app_data(qs->ssl, &qs->conn_ref);
SSL_set_connect_state(qs->ssl);
SSL_set_quic_use_legacy_codepoint(qs->ssl, 0);
@@ -367,107 +342,6 @@ static int quic_init_ssl(struct quicsocket *qs)
return 0;
}
#elif defined(USE_GNUTLS)
-static int secret_func(gnutls_session_t ssl,
- gnutls_record_encryption_level_t gtls_level,
- const void *rx_secret,
- const void *tx_secret, size_t secretlen)
-{
- struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- int level =
- ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
-
- if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
- ngtcp2_crypto_derive_and_install_rx_key(
- qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
- return 0;
-
- if(ngtcp2_crypto_derive_and_install_tx_key(
- qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
- return 0;
-
- if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
- if(init_ngh3_conn(qs) != CURLE_OK)
- return -1;
- }
-
- return 0;
-}
-
-static int read_func(gnutls_session_t ssl,
- gnutls_record_encryption_level_t gtls_level,
- gnutls_handshake_description_t htype, const void *data,
- size_t len)
-{
- struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- ngtcp2_crypto_level level =
- ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
- int rv;
-
- if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
- return 0;
-
- rv = write_client_handshake(qs, level, data, len);
- if(rv == 0)
- return -1;
-
- return 0;
-}
-
-static int alert_read_func(gnutls_session_t ssl,
- gnutls_record_encryption_level_t gtls_level,
- gnutls_alert_level_t alert_level,
- gnutls_alert_description_t alert_desc)
-{
- struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- (void)gtls_level;
- (void)alert_level;
-
- qs->tls_alert = alert_desc;
- return 1;
-}
-
-static int tp_recv_func(gnutls_session_t ssl, const uint8_t *data,
- size_t data_size)
-{
- struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- ngtcp2_transport_params params;
-
- if(ngtcp2_decode_transport_params(
- &params, NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
- data, data_size) != 0)
- return -1;
-
- if(ngtcp2_conn_set_remote_transport_params(qs->qconn, &params) != 0)
- return -1;
-
- return 0;
-}
-
-static int tp_send_func(gnutls_session_t ssl, gnutls_buffer_t extdata)
-{
- struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- uint8_t paramsbuf[64];
- ngtcp2_transport_params params;
- ssize_t nwrite;
- int rc;
-
- ngtcp2_conn_get_local_transport_params(qs->qconn, &params);
- nwrite = ngtcp2_encode_transport_params(
- paramsbuf, sizeof(paramsbuf), NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
- &params);
- if(nwrite < 0) {
- H3BUGF(fprintf(stderr, "ngtcp2_encode_transport_params: %s\n",
- ngtcp2_strerror((int)nwrite)));
- return -1;
- }
-
- rc = gnutls_buffer_append_data(extdata, paramsbuf, nwrite);
- if(rc < 0)
- return rc;
-
- return (int)nwrite;
-}
-
static int quic_init_ssl(struct quicsocket *qs)
{
gnutls_datum_t alpn[2];
@@ -478,26 +352,17 @@ static int quic_init_ssl(struct quicsocket *qs)
DEBUGASSERT(!qs->ssl);
gnutls_init(&qs->ssl, GNUTLS_CLIENT);
- gnutls_session_set_ptr(qs->ssl, qs);
+ gnutls_session_set_ptr(qs->ssl, &qs->conn_ref);
- rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL);
- if(rc < 0) {
- H3BUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
- gnutls_strerror(rc)));
+ if(ngtcp2_crypto_gnutls_configure_client_session(qs->ssl) != 0) {
+ H3BUGF(fprintf(stderr,
+ "ngtcp2_crypto_gnutls_configure_client_session failed\n"));
return 1;
}
- gnutls_handshake_set_secret_function(qs->ssl, secret_func);
- gnutls_handshake_set_read_function(qs->ssl, read_func);
- gnutls_alert_set_read_function(qs->ssl, alert_read_func);
-
- rc = gnutls_session_ext_register(qs->ssl, "QUIC Transport Parameters",
- NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_V1, GNUTLS_EXT_TLS,
- tp_recv_func, tp_send_func, NULL, NULL, NULL,
- GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
- GNUTLS_EXT_FLAG_EE);
+ rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL);
if(rc < 0) {
- H3BUGF(fprintf(stderr, "gnutls_session_ext_register failed: %s\n",
+ H3BUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
gnutls_strerror(rc)));
return 1;
}
@@ -546,7 +411,105 @@ static int quic_init_ssl(struct quicsocket *qs)
gnutls_server_name_set(qs->ssl, GNUTLS_NAME_DNS, hostname, strlen(hostname));
return 0;
}
+#elif defined(USE_WOLFSSL)
+
+static WOLFSSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+
+ if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+ return NULL;
+ }
+
+ wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
+
+ if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
+ char error_buffer[256];
+ ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
+ failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
+ return NULL;
+ }
+
+ if(wolfSSL_CTX_set1_groups_list(ssl_ctx, (char *)QUIC_GROUPS) != 1) {
+ failf(data, "SSL_CTX_set1_groups_list failed");
+ return NULL;
+ }
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+#if defined(HAVE_SECRET_CALLBACK)
+ wolfSSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
+#else
+ failf(data, "wolfSSL was built without keylog callback");
+ return NULL;
+#endif
+ }
+
+ if(conn->ssl_config.verifypeer) {
+ const char * const ssl_cafile = conn->ssl_config.CAfile;
+ const char * const ssl_capath = conn->ssl_config.CApath;
+
+ if(ssl_cafile || ssl_capath) {
+ wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ /* tell wolfSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!wolfSSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return NULL;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* verifying the peer without any CA certificates won't work so
+ use wolfssl's built-in default as fallback */
+ wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
+ }
#endif
+ }
+ else {
+ wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
+ }
+
+ return ssl_ctx;
+}
+
+/** SSL callbacks ***/
+
+static int quic_init_ssl(struct quicsocket *qs)
+{
+ const uint8_t *alpn = NULL;
+ size_t alpnlen = 0;
+ /* this will need some attention when HTTPS proxy over QUIC get fixed */
+ const char * const hostname = qs->conn->host.name;
+
+ DEBUGASSERT(!qs->ssl);
+ qs->ssl = SSL_new(qs->sslctx);
+
+ wolfSSL_set_app_data(qs->ssl, &qs->conn_ref);
+ wolfSSL_set_connect_state(qs->ssl);
+ wolfSSL_set_quic_use_legacy_codepoint(qs->ssl, 0);
+
+ alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
+ alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
+ if(alpn)
+ wolfSSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
+
+ /* set SNI */
+ wolfSSL_UseSNI(qs->ssl, WOLFSSL_SNI_HOST_NAME,
+ hostname, (unsigned short)strlen(hostname));
+
+ return 0;
+}
+#endif /* defined(USE_WOLFSSL) */
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
@@ -571,7 +534,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
void *user_data, void *stream_user_data)
{
struct quicsocket *qs = (struct quicsocket *)user_data;
- ssize_t nconsumed;
+ nghttp3_ssize nconsumed;
int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
(void)offset;
(void)stream_user_data;
@@ -579,6 +542,9 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
nconsumed =
nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
if(nconsumed < 0) {
+ ngtcp2_connection_close_error_set_application_error(
+ &qs->last_error, nghttp3_err_infer_quic_app_error_code((int)nconsumed),
+ NULL, 0);
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -629,6 +595,8 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
app_error_code);
if(rv) {
+ ngtcp2_connection_close_error_set_application_error(
+ &qs->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -735,6 +703,23 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
return 0;
}
+static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_crypto_level level,
+ void *user_data)
+{
+ struct quicsocket *qs = (struct quicsocket *)user_data;
+ (void)tconn;
+
+ if(level != NGTCP2_CRYPTO_LEVEL_APPLICATION) {
+ return 0;
+ }
+
+ if(init_ngh3_conn(qs) != CURLE_OK) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
@@ -773,6 +758,9 @@ static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_get_path_challenge_data_cb,
cb_stream_stop_sending,
NULL, /* version_negotiation */
+ cb_recv_rx_key,
+ NULL, /* recv_tx_key */
+ NULL, /* early_data_rejected */
};
/*
@@ -818,6 +806,10 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
result = quic_set_client_cert(data, qs);
if(result)
return result;
+#elif defined(USE_WOLFSSL)
+ qs->sslctx = quic_ssl_ctx(data);
+ if(!qs->sslctx)
+ return CURLE_QUIC_CONNECT_ERROR;
#endif
if(quic_init_ssl(qs))
@@ -855,6 +847,29 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl);
+ ngtcp2_connection_close_error_default(&qs->last_error);
+
+#if defined(__linux__) && defined(UDP_SEGMENT) && defined(HAVE_SENDMSG)
+ qs->no_gso = FALSE;
+#else
+ qs->no_gso = TRUE;
+#endif
+
+ qs->num_blocked_pkt = 0;
+ qs->num_blocked_pkt_sent = 0;
+ memset(&qs->blocked_pkt, 0, sizeof(qs->blocked_pkt));
+
+ qs->pktbuflen = NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE * MAX_PKT_BURST;
+ qs->pktbuf = malloc(qs->pktbuflen);
+ if(!qs->pktbuf) {
+ ngtcp2_conn_del(qs->qconn);
+ qs->qconn = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ qs->conn_ref.get_conn = get_conn;
+ qs->conn_ref.user_data = qs;
+
return CURLE_OK;
}
@@ -899,18 +914,14 @@ static void qs_disconnect(struct quicsocket *qs)
char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
ngtcp2_tstamp ts;
ngtcp2_ssize rc;
- ngtcp2_connection_close_error errorcode;
if(!qs->conn) /* already closed */
return;
- ngtcp2_connection_close_error_set_application_error(&errorcode,
- NGHTTP3_H3_NO_ERROR,
- NULL, 0);
ts = timestamp();
rc = ngtcp2_conn_write_connection_close(qs->qconn, NULL, /* path */
NULL, /* pkt_info */
(uint8_t *)buffer, sizeof(buffer),
- &errorcode, ts);
+ &qs->last_error, ts);
if(rc > 0) {
while((send(qs->conn->sock[FIRSTSOCKET], buffer, rc, 0) == -1) &&
SOCKERRNO == EINTR);
@@ -926,6 +937,8 @@ static void qs_disconnect(struct quicsocket *qs)
SSL_free(qs->ssl);
#elif defined(USE_GNUTLS)
gnutls_deinit(qs->ssl);
+#elif defined(USE_WOLFSSL)
+ wolfSSL_free(qs->ssl);
#endif
qs->ssl = NULL;
#ifdef USE_GNUTLS
@@ -934,10 +947,13 @@ static void qs_disconnect(struct quicsocket *qs)
qs->cred = NULL;
}
#endif
+ free(qs->pktbuf);
nghttp3_conn_del(qs->h3conn);
ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
SSL_CTX_free(qs->sslctx);
+#elif defined(USE_WOLFSSL)
+ wolfSSL_CTX_free(qs->sslctx);
#endif
}
@@ -1006,6 +1022,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
H3BUGF(infof(data, "cb_h3_stream_close CALLED"));
stream->closed = TRUE;
+ stream->error3 = app_error_code;
Curl_expire(data, 0, EXPIRE_QUIC);
/* make sure that ngh3_stream_recv is called again to complete the transfer
even if there are no more packets to be received from the server. */
@@ -1117,6 +1134,10 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
return -1;
}
}
+
+ if(stream->status_code / 100 != 1) {
+ stream->bodystarted = TRUE;
+ }
return 0;
}
@@ -1139,9 +1160,10 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
char line[14]; /* status line is always 13 characters long */
size_t ncopy;
- int status = decode_status_code(h3val.base, h3val.len);
- DEBUGASSERT(status != -1);
- ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", status);
+ stream->status_code = decode_status_code(h3val.base, h3val.len);
+ DEBUGASSERT(stream->status_code != -1);
+ ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
+ stream->status_code);
result = write_data(stream, line, ncopy);
if(result) {
return -1;
@@ -1171,16 +1193,36 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
return 0;
}
-static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
- uint64_t app_error_code,
- void *user_data,
- void *stream_user_data)
+static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
{
+ struct quicsocket *qs = user_data;
+ int rv;
+ (void)conn;
+ (void)stream_user_data;
+
+ rv = ngtcp2_conn_shutdown_stream_read(qs->qconn, stream_id, app_error_code);
+ if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data) {
+ struct quicsocket *qs = user_data;
+ int rv;
(void)conn;
- (void)stream_id;
- (void)app_error_code;
- (void)user_data;
(void)stream_user_data;
+
+ rv = ngtcp2_conn_shutdown_stream_write(qs->qconn, stream_id, app_error_code);
+ if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
return 0;
}
@@ -1195,9 +1237,9 @@ static nghttp3_callbacks ngh3_callbacks = {
NULL, /* begin_trailers */
cb_h3_recv_header,
NULL, /* end_trailers */
- cb_h3_send_stop_sending,
+ cb_h3_stop_sending,
NULL, /* end_stream */
- NULL, /* reset_stream */
+ cb_h3_reset_stream,
NULL /* shutdown */
};
@@ -1333,6 +1375,24 @@ static ssize_t ngh3_stream_recv(struct Curl_easy *data,
}
if(stream->closed) {
+ if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was not closed cleanly: (err %" PRIu64
+ ")",
+ stream->stream3_id, stream->error3);
+ *curlcode = CURLE_HTTP3;
+ return -1;
+ }
+
+ if(!stream->bodystarted) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
+ " all response header fields, treated as error",
+ stream->stream3_id);
+ *curlcode = CURLE_HTTP3;
+ return -1;
+ }
+
*curlcode = CURLE_OK;
return 0;
}
@@ -1344,7 +1404,7 @@ static ssize_t ngh3_stream_recv(struct Curl_easy *data,
/* this amount of data has now been acked on this stream */
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
- size_t datalen, void *user_data,
+ uint64_t datalen, void *user_data,
void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
@@ -1368,10 +1428,10 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
return 0;
}
-static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
- nghttp3_vec *vec, size_t veccnt,
- uint32_t *pflags, void *user_data,
- void *stream_user_data)
+static nghttp3_ssize cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
+ nghttp3_vec *vec, size_t veccnt,
+ uint32_t *pflags, void *user_data,
+ void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
size_t nread;
@@ -1482,6 +1542,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
nva[i].namelen = hreq->header[i].namelen;
nva[i].value = (unsigned char *)hreq->header[i].value;
nva[i].valuelen = hreq->header[i].valuelen;
+ nva[i].flags = NGHTTP3_NV_FLAG_NONE;
}
}
@@ -1550,6 +1611,11 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data,
curl_socket_t sockfd = conn->sock[sockindex];
struct HTTP *stream = data->req.p.http;
+ if(stream->closed) {
+ *curlcode = CURLE_HTTP3;
+ return -1;
+ }
+
if(!stream->h3req) {
CURLcode result = http_request(data, mem, len);
if(result) {
@@ -1626,12 +1692,23 @@ static CURLcode ng_has_connected(struct Curl_easy *data,
if(result)
return result;
infof(data, "Verified certificate just fine");
-#else
+#elif defined(USE_GNUTLS)
result = Curl_gtls_verifyserver(data, conn, conn->quic->ssl, FIRSTSOCKET);
+#elif defined(USE_WOLFSSL)
+ char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+ if(!snihost ||
+ (wolfSSL_check_domain_name(conn->quic->ssl, snihost) == SSL_FAILURE))
+ return CURLE_PEER_FAILED_VERIFICATION;
+ infof(data, "Verified certificate just fine");
#endif
}
else
infof(data, "Skipped certificate verification");
+#ifdef USE_OPENSSL
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, conn->quic->ssl);
+#endif
return result;
}
@@ -1704,7 +1781,17 @@ static CURLcode ng_process_ingress(struct Curl_easy *data,
rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
if(rv) {
- /* TODO Send CONNECTION_CLOSE if possible */
+ if(!qs->last_error.error_code) {
+ if(rv == NGTCP2_ERR_CRYPTO) {
+ ngtcp2_connection_close_error_set_transport_error_tls_alert(
+ &qs->last_error, ngtcp2_conn_get_tls_alert(qs->qconn), NULL, 0);
+ }
+ else {
+ ngtcp2_connection_close_error_set_transport_error_liberr(
+ &qs->last_error, rv, NULL, 0);
+ }
+ }
+
if(rv == NGTCP2_ERR_CRYPTO)
/* this is a "TLS problem", but a failed certificate verification
is a common reason for this */
@@ -1716,32 +1803,231 @@ static CURLcode ng_process_ingress(struct Curl_easy *data,
return CURLE_OK;
}
+static CURLcode do_sendmsg(size_t *sent, struct Curl_easy *data, int sockfd,
+ struct quicsocket *qs, const uint8_t *pkt,
+ size_t pktlen, size_t gsolen);
+
+static CURLcode send_packet_no_gso(size_t *psent, struct Curl_easy *data,
+ int sockfd, struct quicsocket *qs,
+ const uint8_t *pkt, size_t pktlen,
+ size_t gsolen)
+{
+ const uint8_t *p, *end = pkt + pktlen;
+ size_t sent;
+
+ *psent = 0;
+
+ for(p = pkt; p < end; p += gsolen) {
+ size_t len = CURLMIN(gsolen, (size_t)(end - p));
+ CURLcode curlcode = do_sendmsg(&sent, data, sockfd, qs, p, len, len);
+ if(curlcode != CURLE_OK) {
+ return curlcode;
+ }
+ *psent += sent;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode do_sendmsg(size_t *psent, struct Curl_easy *data, int sockfd,
+ struct quicsocket *qs, const uint8_t *pkt,
+ size_t pktlen, size_t gsolen)
+{
+#ifdef HAVE_SENDMSG
+ struct iovec msg_iov;
+ struct msghdr msg = {0};
+ ssize_t sent;
+#if defined(__linux__) && defined(UDP_SEGMENT)
+ uint8_t msg_ctrl[32];
+ struct cmsghdr *cm;
+#endif
+
+ *psent = 0;
+ msg_iov.iov_base = (uint8_t *)pkt;
+ msg_iov.iov_len = pktlen;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+#if defined(__linux__) && defined(UDP_SEGMENT)
+ if(pktlen > gsolen) {
+ /* Only set this, when we need it. macOS, for example,
+ * does not seem to like a msg_control of length 0. */
+ msg.msg_control = msg_ctrl;
+ assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(uint16_t)));
+ msg.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
+ cm = CMSG_FIRSTHDR(&msg);
+ cm->cmsg_level = SOL_UDP;
+ cm->cmsg_type = UDP_SEGMENT;
+ cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
+ *(uint16_t *)(void *)CMSG_DATA(cm) = gsolen & 0xffff;
+ }
+#endif
+
+
+ while((sent = sendmsg(sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR)
+ ;
+
+ if(sent == -1) {
+ switch(SOCKERRNO) {
+ case EAGAIN:
+#if EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+#endif
+ return CURLE_AGAIN;
+ case EMSGSIZE:
+ /* UDP datagram is too large; caused by PMTUD. Just let it be lost. */
+ break;
+ case EIO:
+ if(pktlen > gsolen) {
+ /* GSO failure */
+ failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
+ SOCKERRNO);
+ qs->no_gso = TRUE;
+ return send_packet_no_gso(psent, data, sockfd, qs, pkt, pktlen,
+ gsolen);
+ }
+ /* FALLTHROUGH */
+ default:
+ failf(data, "sendmsg() returned %zd (errno %d)", sent, SOCKERRNO);
+ return CURLE_SEND_ERROR;
+ }
+ }
+ else {
+ assert(pktlen == (size_t)sent);
+ }
+#else
+ ssize_t sent;
+ (void)qs;
+ (void)gsolen;
+
+ *psent = 0;
+
+ while((sent = send(sockfd, (const char *)pkt, pktlen, 0)) == -1 &&
+ SOCKERRNO == EINTR)
+ ;
+
+ if(sent == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ return CURLE_AGAIN;
+ }
+ else {
+ failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO);
+ if(SOCKERRNO != EMSGSIZE) {
+ return CURLE_SEND_ERROR;
+ }
+ /* UDP datagram is too large; caused by PMTUD. Just let it be
+ lost. */
+ }
+ }
+#endif
+
+ *psent = pktlen;
+
+ return CURLE_OK;
+}
+
+static CURLcode send_packet(size_t *psent, struct Curl_easy *data, int sockfd,
+ struct quicsocket *qs, const uint8_t *pkt,
+ size_t pktlen, size_t gsolen)
+{
+ if(qs->no_gso && pktlen > gsolen) {
+ return send_packet_no_gso(psent, data, sockfd, qs, pkt, pktlen, gsolen);
+ }
+
+ return do_sendmsg(psent, data, sockfd, qs, pkt, pktlen, gsolen);
+}
+
+static void push_blocked_pkt(struct quicsocket *qs, const uint8_t *pkt,
+ size_t pktlen, size_t gsolen)
+{
+ struct blocked_pkt *blkpkt;
+
+ assert(qs->num_blocked_pkt <
+ sizeof(qs->blocked_pkt) / sizeof(qs->blocked_pkt[0]));
+
+ blkpkt = &qs->blocked_pkt[qs->num_blocked_pkt++];
+
+ blkpkt->pkt = pkt;
+ blkpkt->pktlen = pktlen;
+ blkpkt->gsolen = gsolen;
+}
+
+static CURLcode send_blocked_pkt(struct Curl_easy *data, int sockfd,
+ struct quicsocket *qs)
+{
+ size_t sent;
+ CURLcode curlcode;
+ struct blocked_pkt *blkpkt;
+
+ for(; qs->num_blocked_pkt_sent < qs->num_blocked_pkt;
+ ++qs->num_blocked_pkt_sent) {
+ blkpkt = &qs->blocked_pkt[qs->num_blocked_pkt_sent];
+ curlcode = send_packet(&sent, data, sockfd, qs, blkpkt->pkt,
+ blkpkt->pktlen, blkpkt->gsolen);
+
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ blkpkt->pkt += sent;
+ blkpkt->pktlen -= sent;
+ }
+ return curlcode;
+ }
+ }
+
+ qs->num_blocked_pkt = 0;
+ qs->num_blocked_pkt_sent = 0;
+
+ return CURLE_OK;
+}
+
static CURLcode ng_flush_egress(struct Curl_easy *data,
int sockfd,
struct quicsocket *qs)
{
int rv;
- ssize_t sent;
- ssize_t outlen;
- uint8_t out[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
+ size_t sent;
+ ngtcp2_ssize outlen;
+ uint8_t *outpos = qs->pktbuf;
+ size_t max_udp_payload_size =
+ ngtcp2_conn_get_max_tx_udp_payload_size(qs->qconn);
+ size_t path_max_udp_payload_size =
+ ngtcp2_conn_get_path_max_tx_udp_payload_size(qs->qconn);
+ size_t max_pktcnt =
+ CURLMIN(MAX_PKT_BURST, qs->pktbuflen / max_udp_payload_size);
+ size_t pktcnt = 0;
+ size_t gsolen;
ngtcp2_path_storage ps;
ngtcp2_tstamp ts = timestamp();
ngtcp2_tstamp expiry;
ngtcp2_duration timeout;
int64_t stream_id;
- ssize_t veccnt;
+ nghttp3_ssize veccnt;
int fin;
nghttp3_vec vec[16];
- ssize_t ndatalen;
+ ngtcp2_ssize ndatalen;
uint32_t flags;
+ CURLcode curlcode;
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv) {
failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
ngtcp2_strerror(rv));
+ ngtcp2_connection_close_error_set_transport_error_liberr(&qs->last_error,
+ rv, NULL, 0);
return CURLE_SEND_ERROR;
}
+ if(qs->num_blocked_pkt) {
+ curlcode = send_blocked_pkt(data, sockfd, qs);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+ }
+
ngtcp2_path_storage_zero(&ps);
for(;;) {
@@ -1755,39 +2041,45 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
if(veccnt < 0) {
failf(data, "nghttp3_conn_writev_stream returned error: %s",
nghttp3_strerror((int)veccnt));
+ ngtcp2_connection_close_error_set_application_error(
+ &qs->last_error,
+ nghttp3_err_infer_quic_app_error_code((int)veccnt), NULL, 0);
return CURLE_SEND_ERROR;
}
}
flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
(fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out,
- sizeof(out),
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, outpos,
+ max_udp_payload_size,
&ndatalen, flags, stream_id,
(const ngtcp2_vec *)vec, veccnt, ts);
if(outlen == 0) {
+ if(outpos != qs->pktbuf) {
+ curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
+ outpos - qs->pktbuf, gsolen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ push_blocked_pkt(qs, qs->pktbuf + sent, outpos - qs->pktbuf - sent,
+ gsolen);
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+ }
+
break;
}
if(outlen < 0) {
switch(outlen) {
case NGTCP2_ERR_STREAM_DATA_BLOCKED:
assert(ndatalen == -1);
- rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv) {
- failf(data, "nghttp3_conn_block_stream returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
+ nghttp3_conn_block_stream(qs->h3conn, stream_id);
continue;
case NGTCP2_ERR_STREAM_SHUT_WR:
assert(ndatalen == -1);
- rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id);
- if(rv) {
- failf(data,
- "nghttp3_conn_shutdown_stream_write returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
+ nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id);
continue;
case NGTCP2_ERR_WRITE_MORE:
assert(ndatalen >= 0);
@@ -1802,6 +2094,8 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
assert(ndatalen == -1);
failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));
+ ngtcp2_connection_close_error_set_transport_error_liberr(
+ &qs->last_error, (int)outlen, NULL, 0);
return CURLE_SEND_ERROR;
}
}
@@ -1814,20 +2108,61 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
}
}
- while((sent = send(sockfd, (const char *)out, outlen, 0)) == -1 &&
- SOCKERRNO == EINTR)
- ;
+ outpos += outlen;
- if(sent == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- /* TODO Cache packet */
- break;
+ if(pktcnt == 0) {
+ gsolen = outlen;
+ }
+ else if((size_t)outlen > gsolen ||
+ (gsolen > path_max_udp_payload_size &&
+ (size_t)outlen != gsolen)) {
+ /* Packet larger than path_max_udp_payload_size is PMTUD probe
+ packet and it might not be sent because of EMSGSIZE. Send
+ them separately to minimize the loss. */
+ curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
+ outpos - outlen - qs->pktbuf, gsolen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ push_blocked_pkt(qs, qs->pktbuf + sent,
+ outpos - outlen - qs->pktbuf - sent, gsolen);
+ push_blocked_pkt(qs, outpos - outlen, outlen, outlen);
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
}
- else {
- failf(data, "send() returned %zd (errno %d)", sent,
- SOCKERRNO);
- return CURLE_SEND_ERROR;
+ curlcode = send_packet(&sent, data, sockfd, qs, outpos - outlen, outlen,
+ outlen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ assert(0 == sent);
+ push_blocked_pkt(qs, outpos - outlen, outlen, outlen);
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+
+ pktcnt = 0;
+ outpos = qs->pktbuf;
+ continue;
+ }
+
+ if(++pktcnt >= max_pktcnt || (size_t)outlen < gsolen) {
+ curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
+ outpos - qs->pktbuf, gsolen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ push_blocked_pkt(qs, qs->pktbuf + sent, outpos - qs->pktbuf - sent,
+ gsolen);
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
}
+
+ pktcnt = 0;
+ outpos = qs->pktbuf;
}
}
@@ -1894,4 +2229,26 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
return Curl_dyn_len(&stream->overflow) > 0;
}
+/*
+ * Called from transfer.c:Curl_readwrite when neither HTTP level read
+ * nor write is performed. It is a good place to handle timer expiry
+ * for QUIC transport.
+ */
+CURLcode Curl_quic_idle(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+ struct quicsocket *qs = conn->quic;
+
+ if(ngtcp2_conn_get_expiry(qs->qconn) > timestamp()) {
+ return CURLE_OK;
+ }
+
+ if(ng_flush_egress(data, sockfd, qs)) {
+ return CURLE_SEND_ERROR;
+ }
+
+ return CURLE_OK;
+}
+
#endif
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.h b/Utilities/cmcurl/lib/vquic/ngtcp2.h
index 501453042..6539f5fef 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.h
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,20 +20,36 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGTCP2
-#include <ngtcp2/ngtcp2.h>
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#include <ngtcp2/ngtcp2_crypto.h>
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/ssl.h>
#elif defined(USE_GNUTLS)
#include <gnutls/gnutls.h>
+#elif defined(USE_WOLFSSL)
+#include <wolfssl/options.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/quic.h>
#endif
+struct blocked_pkt {
+ const uint8_t *pkt;
+ size_t pktlen;
+ size_t gsolen;
+};
+
struct quicsocket {
struct connectdata *conn; /* point back to the connection */
ngtcp2_conn *qconn;
@@ -42,17 +58,29 @@ struct quicsocket {
uint32_t version;
ngtcp2_settings settings;
ngtcp2_transport_params transport_params;
+ ngtcp2_connection_close_error last_error;
+ ngtcp2_crypto_conn_ref conn_ref;
#ifdef USE_OPENSSL
SSL_CTX *sslctx;
SSL *ssl;
#elif defined(USE_GNUTLS)
gnutls_certificate_credentials_t cred;
gnutls_session_t ssl;
+#elif defined(USE_WOLFSSL)
+ WOLFSSL_CTX *sslctx;
+ WOLFSSL *ssl;
#endif
- /* the last TLS alert description generated by the local endpoint */
- uint8_t tls_alert;
struct sockaddr_storage local_addr;
socklen_t local_addrlen;
+ bool no_gso;
+ uint8_t *pktbuf;
+ size_t pktbuflen;
+ /* the number of entries in blocked_pkt */
+ size_t num_blocked_pkt;
+ /* the number of processed entries in blocked_pkt */
+ size_t num_blocked_pkt_sent;
+ /* the packets blocked by sendmsg (EAGAIN or EWOULDBLOCK) */
+ struct blocked_pkt blocked_pkt[2];
nghttp3_conn *h3conn;
nghttp3_settings h3settings;
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c
index bfdc966a8..a52a7e8e2 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.c
+++ b/Utilities/cmcurl/lib/vquic/quiche.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -201,23 +203,31 @@ static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
-
if(conn->ssl_config.verifypeer) {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- /* tell OpenSSL where to find CA certificates that are used to verify
- the server's certificate. */
- if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return NULL;
+ const char * const ssl_cafile = conn->ssl_config.CAfile;
+ const char * const ssl_capath = conn->ssl_config.CApath;
+ if(ssl_cafile || ssl_capath) {
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ /* tell OpenSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return NULL;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* verifying the peer without any CA certificates won't work so
+ use openssl's built-in default as fallback */
+ SSL_CTX_set_default_verify_paths(ssl_ctx);
}
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+#endif
}
}
return ssl_ctx;
@@ -248,6 +258,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
struct quicsocket *qs = &conn->hequic[sockindex];
char ipbuf[40];
int port;
+ int rv;
#ifdef DEBUG_QUICHE
/* initialize debug log callback only once */
@@ -293,8 +304,16 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
if(result)
return result;
+ qs->local_addrlen = sizeof(qs->local_addr);
+ rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
+ &qs->local_addrlen);
+ if(rv == -1)
+ return CURLE_QUIC_CONNECT_ERROR;
+
qs->conn = quiche_conn_new_with_tls((const uint8_t *) qs->scid,
- sizeof(qs->scid), NULL, 0, addr, addrlen,
+ sizeof(qs->scid), NULL, 0,
+ (struct sockaddr *)&qs->local_addr,
+ qs->local_addrlen, addr, addrlen,
qs->cfg, qs->ssl, false);
if(!qs->conn) {
failf(data, "can't create quiche connection");
@@ -397,6 +416,10 @@ static CURLcode quiche_has_connected(struct Curl_easy *data,
qs->cfg = NULL;
qs->conn = NULL;
}
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, qs->ssl);
+
return CURLE_OK;
fail:
quiche_h3_config_free(qs->h3config);
@@ -468,6 +491,8 @@ static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
recv_info.from = (struct sockaddr *) &from;
recv_info.from_len = from_len;
+ recv_info.to = (struct sockaddr *) &qs->local_addr;
+ recv_info.to_len = qs->local_addrlen;
recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info);
if(recvd == QUICHE_ERR_DONE)
@@ -856,4 +881,15 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
return FALSE;
}
+/*
+ * Called from transfer.c:Curl_readwrite when neither HTTP level read
+ * nor write is performed. It is a good place to handle timer expiry
+ * for QUIC transport.
+ */
+CURLcode Curl_quic_idle(struct Curl_easy *data)
+{
+ (void)data;
+ return CURLE_OK;
+}
+
#endif
diff --git a/Utilities/cmcurl/lib/vquic/quiche.h b/Utilities/cmcurl/lib/vquic/quiche.h
index 759a20bba..2da65f5f4 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.h
+++ b/Utilities/cmcurl/lib/vquic/quiche.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -47,6 +49,8 @@ struct quicsocket {
SSL_CTX *sslctx;
SSL *ssl;
bool h3_recving; /* TRUE when in h3-body-reading state */
+ struct sockaddr_storage local_addr;
+ socklen_t local_addrlen;
};
#endif
diff --git a/Utilities/cmcurl/lib/vquic/vquic.c b/Utilities/cmcurl/lib/vquic/vquic.c
index be2a65f45..e52a4f301 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.c
+++ b/Utilities/cmcurl/lib/vquic/vquic.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vquic/vquic.h b/Utilities/cmcurl/lib/vquic/vquic.h
index 3df138f10..8f599a8f4 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.h
+++ b/Utilities/cmcurl/lib/vquic/vquic.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index 7bf2b0417..0105e4079 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -94,6 +96,13 @@
#include "curl_memory.h"
#include "memdebug.h"
+/* in 0.10.0 or later, ignore deprecated warnings */
+#if defined(__GNUC__) && \
+ (LIBSSH_VERSION_MINOR >= 10) || \
+ (LIBSSH_VERSION_MAJOR > 0)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
/* A recent macro provided by libssh. Or make our own. */
#ifndef SSH_STRING_FREE_CHAR
#define SSH_STRING_FREE_CHAR(x) \
@@ -954,10 +963,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
rc = sftp_init(sshc->sftp_session);
if(rc != SSH_OK) {
- rc = sftp_get_error(sshc->sftp_session);
failf(data, "Failure initializing sftp session: %s",
ssh_get_error(sshc->ssh_session));
- MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
+ MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(SSH_FX_FAILURE));
break;
}
state(data, SSH_SFTP_REALPATH);
@@ -1658,7 +1666,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW) {
@@ -1970,10 +1978,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
ssh_disconnect(sshc->ssh_session);
- /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
- explicitly mark it as closed with the memdebug macro: */
- fake_sclose(conn->sock[FIRSTSOCKET]);
- conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+ if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
+ /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
+ explicitly mark it as closed with the memdebug macro. This libssh
+ bug is fixed in 0.10.0. */
+ fake_sclose(conn->sock[FIRSTSOCKET]);
+ conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+ }
SSH_STRING_FREE_CHAR(sshc->homedir);
data->state.most_recent_ftp_entrypath = NULL;
@@ -2906,32 +2917,33 @@ static void sftp_quote_stat(struct Curl_easy *data)
}
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
- else if(strncasecompare(cmd, "atime", 5)) {
+ else if(strncasecompare(cmd, "atime", 5) ||
+ strncasecompare(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
+ bool fail = FALSE;
if(date == -1) {
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect access date format");
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- return;
+ failf(data, "incorrect date format for %.*s", 5, cmd);
+ fail = TRUE;
}
- sshc->quote_attrs->atime = (uint32_t)date;
- sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
- }
- else if(strncasecompare(cmd, "mtime", 5)) {
- time_t date = Curl_getdate_capped(sshc->quote_path1);
- if(date == -1) {
+#if SIZEOF_TIME_T > 4
+ else if(date > 0xffffffff) {
+ failf(data, "date overflow");
+ fail = TRUE; /* avoid setting a capped time */
+ }
+#endif
+ if(fail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect modification date format");
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
- sshc->quote_attrs->mtime = (uint32_t)date;
+ if(strncasecompare(cmd, "atime", 5))
+ sshc->quote_attrs->atime = (uint32_t)date;
+ else /* mtime */
+ sshc->quote_attrs->mtime = (uint32_t)date;
+
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
}
@@ -2956,7 +2968,7 @@ void Curl_ssh_cleanup(void)
void Curl_ssh_version(char *buffer, size_t buflen)
{
- (void)msnprintf(buffer, buflen, "libssh/%s", CURL_LIBSSH_VERSION);
+ (void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0));
}
#endif /* USE_LIBSSH */
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index d26926386..5a2c0f8bb 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* #define CURL_LIBSSH2_DEBUG */
@@ -437,9 +439,45 @@ static int sshkeycallback(struct Curl_easy *easy,
#else
#define session_startup(x,y) libssh2_session_startup(x, (int)y)
#endif
+static int convert_ssh2_keytype(int sshkeytype)
+{
+ int keytype = CURLKHTYPE_UNKNOWN;
+ switch(sshkeytype) {
+ case LIBSSH2_HOSTKEY_TYPE_RSA:
+ keytype = CURLKHTYPE_RSA;
+ break;
+ case LIBSSH2_HOSTKEY_TYPE_DSS:
+ keytype = CURLKHTYPE_DSS;
+ break;
+#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
+ case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
+ keytype = CURLKHTYPE_ECDSA;
+ break;
+#endif
+#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
+ case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
+ keytype = CURLKHTYPE_ECDSA;
+ break;
+#endif
+#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
+ case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
+ keytype = CURLKHTYPE_ECDSA;
+ break;
+#endif
+#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
+ case LIBSSH2_HOSTKEY_TYPE_ED25519:
+ keytype = CURLKHTYPE_ED25519;
+ break;
+#endif
+ }
+ return keytype;
+}
static CURLcode ssh_knownhost(struct Curl_easy *data)
{
+ int sshkeytype = 0;
+ size_t keylen = 0;
+ int rc = 0;
CURLcode result = CURLE_OK;
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
@@ -448,11 +486,8 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
struct libssh2_knownhost *host = NULL;
- int rc;
- int keytype;
- size_t keylen;
const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
- &keylen, &keytype);
+ &keylen, &sshkeytype);
int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
int keybit = 0;
@@ -464,12 +499,12 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
*/
enum curl_khmatch keymatch;
curl_sshkeycallback func =
- data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
+ data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback;
struct curl_khkey knownkey;
struct curl_khkey *knownkeyp = NULL;
struct curl_khkey foundkey;
- switch(keytype) {
+ switch(sshkeytype) {
case LIBSSH2_HOSTKEY_TYPE_RSA:
keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
break;
@@ -533,16 +568,14 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
knownkey.key = host->key;
knownkey.len = 0;
- knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
- CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+ knownkey.keytype = convert_ssh2_keytype(sshkeytype);
knownkeyp = &knownkey;
}
/* setup 'foundkey' */
foundkey.key = remotekey;
foundkey.len = keylen;
- foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
- CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+ foundkey.keytype = convert_ssh2_keytype(sshkeytype);
/*
* if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
@@ -639,7 +672,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
#ifdef LIBSSH2_HOSTKEY_HASH_SHA256
/* The fingerprint points to static storage (!), don't free() it. */
fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
- LIBSSH2_HOSTKEY_HASH_SHA256);
+ LIBSSH2_HOSTKEY_HASH_SHA256);
#else
const char *hostkey;
size_t len = 0;
@@ -654,8 +687,8 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
if(!fingerprint) {
failf(data,
- "Denied establishing ssh session: sha256 fingerprint "
- "not available");
+ "Denied establishing ssh session: sha256 fingerprint "
+ "not available");
state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
@@ -715,7 +748,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
const char *fingerprint = NULL;
fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
- LIBSSH2_HOSTKEY_HASH_MD5);
+ LIBSSH2_HOSTKEY_HASH_MD5);
if(fingerprint) {
/* The fingerprint points to static storage (!), don't free() it. */
@@ -748,7 +781,31 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
}
if(!pubkey_md5 && !pubkey_sha256) {
- return ssh_knownhost(data);
+ if(data->set.ssh_hostkeyfunc) {
+ size_t keylen = 0;
+ int sshkeytype = 0;
+ int rc = 0;
+ /* we handle the process to the callback*/
+ const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
+ &keylen, &sshkeytype);
+ if(remotekey) {
+ int keytype = convert_ssh2_keytype(sshkeytype);
+ Curl_set_in_callback(data, true);
+ rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
+ keytype, remotekey, keylen);
+ Curl_set_in_callback(data, false);
+ if(rc!= CURLKHMATCH_OK) {
+ state(data, SSH_SESSION_FREE);
+ }
+ }
+ else {
+ state(data, SSH_SESSION_FREE);
+ }
+ return CURLE_OK;
+ }
+ else {
+ return ssh_knownhost(data);
+ }
}
else {
/* as we already matched, we skip the check for known hosts */
@@ -1698,32 +1755,35 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
}
- else if(strncasecompare(cmd, "atime", 5)) {
+ else if(strncasecompare(cmd, "atime", 5) ||
+ strncasecompare(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
+ bool fail = FALSE;
+
if(date == -1) {
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect access date format");
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
+ failf(data, "incorrect date format for %.*s", 5, cmd);
+ fail = TRUE;
}
- sshp->quote_attrs.atime = (unsigned long)date;
- sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
- }
- else if(strncasecompare(cmd, "mtime", 5)) {
- time_t date = Curl_getdate_capped(sshc->quote_path1);
- if(date == -1) {
+#if SIZEOF_TIME_T > SIZEOF_LONG
+ if(date > 0xffffffff) {
+ /* if 'long' can't old >32bit, this date cannot be sent */
+ failf(data, "date overflow");
+ fail = TRUE;
+ }
+#endif
+ if(fail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect modification date format");
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- sshp->quote_attrs.mtime = (unsigned long)date;
+ if(strncasecompare(cmd, "atime", 5))
+ sshp->quote_attrs.atime = (unsigned long)date;
+ else /* mtime */
+ sshp->quote_attrs.mtime = (unsigned long)date;
+
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
}
@@ -2278,7 +2338,8 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
- result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
+ result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
+ sshp->readdir_filename);
state(data, SSH_SFTP_READDIR_LINK);
if(!result)
break;
@@ -2445,7 +2506,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
if(to_t == CURL_OFFT_FLOW)
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 30d82e576..13bb8aa2d 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -20,14 +20,16 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
-#if defined(HAVE_LIBSSH2_H)
+#if defined(USE_LIBSSH2)
#include <libssh2.h>
#include <libssh2_sftp.h>
-#elif defined(HAVE_LIBSSH_LIBSSH_H)
+#elif defined(USE_LIBSSH)
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#elif defined(USE_WOLFSSH)
@@ -209,11 +211,7 @@ struct ssh_conn {
#endif /* USE_LIBSSH */
};
-#if defined(USE_LIBSSH)
-
-#define CURL_LIBSSH_VERSION ssh_version(0)
-
-#elif defined(USE_LIBSSH2)
+#if defined(USE_LIBSSH2)
/* Feature detection based on version numbers to better work with
non-configure platforms */
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index 85f294196..c2f85f3fe 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 91f4416e8..1221ce8c8 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -74,9 +76,9 @@ struct cafile_parser {
#define CAFILE_SOURCE_PATH 1
#define CAFILE_SOURCE_BLOB 2
struct cafile_source {
- const int type;
- const char * const data;
- const size_t len;
+ int type;
+ const char *data;
+ size_t len;
};
static void append_dn(void *ctx, const void *buf, size_t len)
@@ -616,11 +618,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
}
if(ca_info_blob) {
- struct cafile_source source = {
- CAFILE_SOURCE_BLOB,
- ca_info_blob->data,
- ca_info_blob->len,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_BLOB;
+ source.data = ca_info_blob->data;
+ source.len = ca_info_blob->len;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -633,11 +635,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
}
if(ssl_cafile) {
- struct cafile_source source = {
- CAFILE_SOURCE_PATH,
- ssl_cafile,
- 0,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_PATH;
+ source.data = ssl_cafile;
+ source.len = 0;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -873,14 +875,14 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
#ifdef USE_HTTP2
if(!strcmp(protocol, ALPN_H2))
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
else
#endif
if(!strcmp(protocol, ALPN_HTTP_1_1))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
else
infof(data, "ALPN, unrecognized protocol %s", protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.h b/Utilities/cmcurl/lib/vtls/bearssl.h
index d72b7d0e2..512535996 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.h
+++ b/Utilities/cmcurl/lib/vtls/bearssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 7a65f92f2..4ee4edea6 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index 202df7e07..cf923f6b8 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index dd8275585..cf3dbc523 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -43,6 +45,7 @@
#include "inet_pton.h"
#include "gtls.h"
#include "vtls.h"
+#include "vauth/vauth.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
@@ -446,7 +449,7 @@ gtls_connect_step1(struct Curl_easy *data,
#ifdef USE_GNUTLS_SRP
if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
- Curl_allow_auth_to_host(data)) {
+ Curl_auth_allowed_to_host(data)) {
infof(data, "Using TLS-SRP username: %s",
SSL_SET_OPTION(primary.username));
@@ -1272,19 +1275,19 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
if(proto.size == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, proto.data,
ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(proto.size == ALPN_HTTP_1_1_LENGTH &&
!memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 642d5f093..abade73f8 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/hostcheck.c b/Utilities/cmcurl/lib/vtls/hostcheck.c
index 8dc97a27d..2a648f20a 100644
--- a/Utilities/cmcurl/lib/vtls/hostcheck.c
+++ b/Utilities/cmcurl/lib/vtls/hostcheck.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/hostcheck.h b/Utilities/cmcurl/lib/vtls/hostcheck.h
index aa966403d..d3c4eab56 100644
--- a/Utilities/cmcurl/lib/vtls/hostcheck.h
+++ b/Utilities/cmcurl/lib/vtls/hostcheck.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include <curl/curl.h>
diff --git a/Utilities/cmcurl/lib/vtls/keylog.c b/Utilities/cmcurl/lib/vtls/keylog.c
index a45945f8f..1952a690c 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.c
+++ b/Utilities/cmcurl/lib/vtls/keylog.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,10 +18,13 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#include "keylog.h"
+#include <curl/curl.h>
/* The last #include files should be: */
#include "curl_memory.h"
diff --git a/Utilities/cmcurl/lib/vtls/keylog.h b/Utilities/cmcurl/lib/vtls/keylog.h
index 63626da90..5d3c675b3 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.h
+++ b/Utilities/cmcurl/lib/vtls/keylog.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index b60b9cac5..fbde8976e 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -819,19 +821,19 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(!strncmp(next_protocol, ALPN_H2, ALPN_H2_LENGTH) &&
!next_protocol[ALPN_H2_LENGTH]) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
!next_protocol[ALPN_HTTP_1_1_LENGTH]) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
}
else {
infof(data, VTLS_INFOF_NO_ALPN);
}
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 1abd331ea..ec3b43bf9 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 751755c23..3971e69b2 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
index e40dfc8d6..3a50d0381 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index cb0509ff5..12cf618f5 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -334,7 +336,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc *model,
char name[MAX_CIPHER_LENGTH + 1];
size_t len;
bool found = FALSE;
- while((*cipher) && (ISSPACE(*cipher)))
+ while((*cipher) && (ISBLANK(*cipher)))
++cipher;
end = strpbrk(cipher, ":, ");
@@ -848,7 +850,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
unsigned int buflen;
SSLNextProtoState state;
- if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) {
+ if(!conn->bits.tls_enable_alpn) {
return;
}
@@ -869,21 +871,21 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, buflen, buf);
break;
#endif
- case SSL_NEXT_PROTO_NEGOTIATED:
- infof(data, "NPN, server accepted to use %.*s", buflen, buf);
+ default:
+ /* ignore SSL_NEXT_PROTO_NEGOTIATED */
break;
}
#ifdef USE_HTTP2
if(buflen == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(buflen == ALPN_HTTP_1_1_LENGTH &&
!memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
/* This callback might get called when PR_Recv() is used within
@@ -891,7 +893,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
* be any "bundle" associated with the connection anymore.
*/
if(conn->bundle)
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
}
@@ -934,8 +936,8 @@ static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
if(cipherInfo.symCipher != ssl_calg_aes_gcm)
goto end;
- /* Enforce ALPN or NPN to do False Start, as an indicator of server
- * compatibility. */
+ /* Enforce ALPN to do False Start, as an indicator of server
+ compatibility. */
rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
&negotiatedExtension);
if(rv != SECSuccess || !negotiatedExtension) {
@@ -2134,12 +2136,6 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
}
#endif
-#ifdef SSL_ENABLE_NPN
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
- ? PR_TRUE : PR_FALSE) != SECSuccess)
- goto error;
-#endif
-
#ifdef SSL_ENABLE_ALPN
if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
? PR_TRUE : PR_FALSE) != SECSuccess)
@@ -2158,15 +2154,15 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
}
#endif
-#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
- if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) {
+#if defined(SSL_ENABLE_ALPN)
+ if(conn->bits.tls_enable_alpn) {
int cur = 0;
unsigned char protocols[128];
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+ && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
#endif
) {
protocols[cur++] = ALPN_H2_LENGTH;
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index 37b364647..454a38f1f 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 635e9c15e..0dc695d7f 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -27,7 +29,7 @@
#include "curl_setup.h"
-#ifdef USE_OPENSSL
+#if defined(USE_QUICHE) || defined(USE_OPENSSL)
#include <limits.h>
@@ -53,6 +55,7 @@
#include "slist.h"
#include "select.h"
#include "vtls.h"
+#include "vauth/vauth.h"
#include "keylog.h"
#include "strcase.h"
#include "hostcheck.h"
@@ -76,10 +79,6 @@
#include <openssl/buffer.h>
#include <openssl/pkcs12.h>
-#ifdef USE_AMISSL
-#include "amigaos.h"
-#endif
-
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
#endif
@@ -217,8 +216,10 @@
* BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30)
* LibreSSL: since 2.5.3 (April 12, 2017)
*/
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) || \
- defined(OPENSSL_IS_BORINGSSL)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20503000L)) || \
+ defined(OPENSSL_IS_BORINGSSL)
#define HAVE_SSL_CTX_SET_EC_CURVES
#endif
@@ -273,6 +274,344 @@ struct ssl_backend_data {
#endif
};
+#define push_certinfo(_label, _num) \
+do { \
+ long info_len = BIO_get_mem_data(mem, &ptr); \
+ Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
+ if(1 != BIO_reset(mem)) \
+ break; \
+} while(0)
+
+static void pubkey_show(struct Curl_easy *data,
+ BIO *mem,
+ int num,
+ const char *type,
+ const char *name,
+ const BIGNUM *bn)
+{
+ char *ptr;
+ char namebuf[32];
+
+ msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+
+ if(bn)
+ BN_print(mem, bn);
+ push_certinfo(namebuf, num);
+}
+
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+#define print_pubkey_BN(_type, _name, _num) \
+ pubkey_show(data, mem, _num, #_type, #_name, _name)
+
+#else
+#define print_pubkey_BN(_type, _name, _num) \
+do { \
+ if(_type->_name) { \
+ pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
+ } \
+} while(0)
+#endif
+
+static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
+{
+ int i, ilen;
+
+ ilen = (int)len;
+ if(ilen < 0)
+ return 1; /* buffer too big */
+
+ i = i2t_ASN1_OBJECT(buf, ilen, a);
+
+ if(i >= ilen)
+ return 1; /* buffer too small */
+
+ return 0;
+}
+
+static void X509V3_ext(struct Curl_easy *data,
+ int certnum,
+ CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+
+ if((int)sk_X509_EXTENSION_num(exts) <= 0)
+ /* no extensions, bail out */
+ return;
+
+ for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ BUF_MEM *biomem;
+ char namebuf[128];
+ BIO *bio_out = BIO_new(BIO_s_mem());
+
+ if(!bio_out)
+ return;
+
+ obj = X509_EXTENSION_get_object(ext);
+
+ asn1_object_dump(obj, namebuf, sizeof(namebuf));
+
+ if(!X509V3_EXT_print(bio_out, ext, 0, 0))
+ ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+ Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
+ biomem->length);
+ BIO_free(bio_out);
+ }
+}
+
+#ifdef OPENSSL_IS_BORINGSSL
+typedef size_t numcert_t;
+#else
+typedef int numcert_t;
+#endif
+
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
+{
+ CURLcode result;
+ STACK_OF(X509) *sk;
+ int i;
+ numcert_t numcerts;
+ BIO *mem;
+
+ DEBUGASSERT(ssl);
+
+ sk = SSL_get_peer_cert_chain(ssl);
+ if(!sk) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ numcerts = sk_X509_num(sk);
+
+ result = Curl_ssl_init_certinfo(data, (int)numcerts);
+ if(result) {
+ return result;
+ }
+
+ mem = BIO_new(BIO_s_mem());
+ if(!mem) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ for(i = 0; i < (int)numcerts; i++) {
+ ASN1_INTEGER *num;
+ X509 *x = sk_X509_value(sk, i);
+ EVP_PKEY *pubkey = NULL;
+ int j;
+ char *ptr;
+ const ASN1_BIT_STRING *psig = NULL;
+
+ X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Subject", i);
+
+ X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Issuer", i);
+
+ BIO_printf(mem, "%lx", X509_get_version(x));
+ push_certinfo("Version", i);
+
+ num = X509_get_serialNumber(x);
+ if(num->type == V_ASN1_NEG_INTEGER)
+ BIO_puts(mem, "-");
+ for(j = 0; j < num->length; j++)
+ BIO_printf(mem, "%02x", num->data[j]);
+ push_certinfo("Serial Number", i);
+
+#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
+ {
+ const X509_ALGOR *sigalg = NULL;
+ X509_PUBKEY *xpubkey = NULL;
+ ASN1_OBJECT *pubkeyoid = NULL;
+
+ X509_get0_signature(&psig, &sigalg, x);
+ if(sigalg) {
+ i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+ push_certinfo("Signature Algorithm", i);
+ }
+
+ xpubkey = X509_get_X509_PUBKEY(x);
+ if(xpubkey) {
+ X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
+ if(pubkeyoid) {
+ i2a_ASN1_OBJECT(mem, pubkeyoid);
+ push_certinfo("Public Key Algorithm", i);
+ }
+ }
+
+ X509V3_ext(data, i, X509_get0_extensions(x));
+ }
+#else
+ {
+ /* before OpenSSL 1.0.2 */
+ X509_CINF *cinf = x->cert_info;
+
+ i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
+ push_certinfo("Signature Algorithm", i);
+
+ i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
+ push_certinfo("Public Key Algorithm", i);
+
+ X509V3_ext(data, i, cinf->extensions);
+
+ psig = x->signature;
+ }
+#endif
+
+ ASN1_TIME_print(mem, X509_get0_notBefore(x));
+ push_certinfo("Start date", i);
+
+ ASN1_TIME_print(mem, X509_get0_notAfter(x));
+ push_certinfo("Expire date", i);
+
+ pubkey = X509_get_pubkey(x);
+ if(!pubkey)
+ infof(data, " Unable to load public key");
+ else {
+ int pktype;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ pktype = EVP_PKEY_id(pubkey);
+#else
+ pktype = pubkey->type;
+#endif
+ switch(pktype) {
+ case EVP_PKEY_RSA:
+ {
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ RSA *rsa;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ rsa = EVP_PKEY_get0_RSA(pubkey);
+#else
+ rsa = pubkey->pkey.rsa;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(n);
+ DECLARE_PKEY_PARAM_BIGNUM(e);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
+#else
+ RSA_get0_key(rsa, &n, &e, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+ BIO_printf(mem, "%d", BN_num_bits(n));
+#else
+ BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ push_certinfo("RSA Public Key", i);
+ print_pubkey_BN(rsa, n, i);
+ print_pubkey_BN(rsa, e, i);
+ FREE_PKEY_PARAM_BIGNUM(n);
+ FREE_PKEY_PARAM_BIGNUM(e);
+ }
+
+ break;
+ }
+ case EVP_PKEY_DSA:
+ {
+#ifndef OPENSSL_NO_DSA
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ DSA *dsa;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ dsa = EVP_PKEY_get0_DSA(pubkey);
+#else
+ dsa = pubkey->pkey.dsa;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(p);
+ DECLARE_PKEY_PARAM_BIGNUM(q);
+ DECLARE_PKEY_PARAM_BIGNUM(g);
+ DECLARE_PKEY_PARAM_BIGNUM(pub_key);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
+#else
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ DSA_get0_key(dsa, &pub_key, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ print_pubkey_BN(dsa, p, i);
+ print_pubkey_BN(dsa, q, i);
+ print_pubkey_BN(dsa, g, i);
+ print_pubkey_BN(dsa, pub_key, i);
+ FREE_PKEY_PARAM_BIGNUM(p);
+ FREE_PKEY_PARAM_BIGNUM(q);
+ FREE_PKEY_PARAM_BIGNUM(g);
+ FREE_PKEY_PARAM_BIGNUM(pub_key);
+ }
+#endif /* !OPENSSL_NO_DSA */
+ break;
+ }
+ case EVP_PKEY_DH:
+ {
+#ifndef HAVE_EVP_PKEY_GET_PARAMS
+ DH *dh;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+ dh = EVP_PKEY_get0_DH(pubkey);
+#else
+ dh = pubkey->pkey.dh;
+#endif /* HAVE_OPAQUE_EVP_PKEY */
+#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
+ {
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+ DECLARE_PKEY_PARAM_BIGNUM(p);
+ DECLARE_PKEY_PARAM_BIGNUM(q);
+ DECLARE_PKEY_PARAM_BIGNUM(g);
+ DECLARE_PKEY_PARAM_BIGNUM(pub_key);
+#ifdef HAVE_EVP_PKEY_GET_PARAMS
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
+ EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
+#else
+ DH_get0_pqg(dh, &p, &q, &g);
+ DH_get0_key(dh, &pub_key, NULL);
+#endif /* HAVE_EVP_PKEY_GET_PARAMS */
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, q, i);
+ print_pubkey_BN(dh, g, i);
+#else
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, g, i);
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ print_pubkey_BN(dh, pub_key, i);
+ FREE_PKEY_PARAM_BIGNUM(p);
+ FREE_PKEY_PARAM_BIGNUM(q);
+ FREE_PKEY_PARAM_BIGNUM(g);
+ FREE_PKEY_PARAM_BIGNUM(pub_key);
+ }
+ break;
+ }
+ }
+ EVP_PKEY_free(pubkey);
+ }
+
+ if(psig) {
+ for(j = 0; j < psig->length; j++)
+ BIO_printf(mem, "%02x:", psig->data[j]);
+ push_certinfo("Signature", i);
+ }
+
+ PEM_write_bio_X509(mem, x);
+ push_certinfo("Cert", i);
+ }
+
+ BIO_free(mem);
+
+ return CURLE_OK;
+}
+
+#endif /* quiche or OpenSSL */
+
+#ifdef USE_OPENSSL
+
static bool ossl_associate_connection(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
@@ -484,36 +823,19 @@ static CURLcode ossl_seed(struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
#else
-#ifndef RANDOM_FILE
- /* if RANDOM_FILE isn't defined, we only perform this if an option tells
- us to! */
- if(data->set.str[STRING_SSL_RANDOM_FILE])
-#define RANDOM_FILE "" /* doesn't matter won't be used */
+#ifdef RANDOM_FILE
+ RAND_load_file(RANDOM_FILE, RAND_LOAD_LENGTH);
+ if(rand_enough())
+ return CURLE_OK;
#endif
- {
- /* let the option override the define */
- RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
- data->set.str[STRING_SSL_RANDOM_FILE]:
- RANDOM_FILE),
- RAND_LOAD_LENGTH);
- if(rand_enough())
- return CURLE_OK;
- }
-#if defined(HAVE_RAND_EGD)
- /* only available in OpenSSL 0.9.5 and later */
+#if defined(HAVE_RAND_EGD) && defined(EGD_SOCKET)
+ /* available in OpenSSL 0.9.5 and later */
/* EGD_SOCKET is set at configure time or not at all */
-#ifndef EGD_SOCKET
- /* If we don't have the define set, we only do this if the egd-option
- is set */
- if(data->set.str[STRING_SSL_EGDSOCKET])
-#define EGD_SOCKET "" /* doesn't matter won't be used */
-#endif
{
/* If there's an option and a define, the option overrides the
define */
- int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
- data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
+ int ret = RAND_egd(EGD_SOCKET);
if(-1 != ret) {
if(rand_enough())
return CURLE_OK;
@@ -812,9 +1134,10 @@ int cert_stuff(struct Curl_easy *data,
SSL_CTX_use_certificate_chain_file(ctx, cert_file);
if(cert_use_result != 1) {
failf(data,
- "could not load PEM client certificate, " OSSL_PACKAGE
+ "could not load PEM client certificate from %s, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
+ (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
return 0;
@@ -832,9 +1155,10 @@ int cert_stuff(struct Curl_easy *data,
SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
if(cert_use_result != 1) {
failf(data,
- "could not load ASN1 client certificate, " OSSL_PACKAGE
+ "could not load ASN1 client certificate from %s, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
+ (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
return 0;
@@ -887,8 +1211,9 @@ int cert_stuff(struct Curl_easy *data,
}
if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
- failf(data, "unable to set client certificate");
- X509_free(params.cert);
+ failf(data, "unable to set client certificate [%s]",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
return 0;
}
X509_free(params.cert); /* we don't need the handle any more... */
@@ -1011,11 +1336,7 @@ int cert_stuff(struct Curl_easy *data,
fail:
EVP_PKEY_free(pri);
X509_free(x509);
-#ifdef USE_AMISSL
- sk_X509_pop_free(ca, Curl_amiga_X509_free);
-#else
sk_X509_pop_free(ca, X509_free);
-#endif
if(!cert_done)
return 0; /* failure! */
break;
@@ -2274,73 +2595,15 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
# define HAS_ALPN 1
#endif
-/* Check for OpenSSL 1.0.1 which has NPN support. */
-#undef HAS_NPN
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L \
- && !defined(OPENSSL_NO_TLSEXT) \
- && !defined(OPENSSL_NO_NEXTPROTONEG)
-# define HAS_NPN 1
-#endif
-
-#ifdef HAS_NPN
-
-/*
- * in is a list of length prefixed strings. this function has to select
- * the protocol we want to use from the list and write its string into out.
- */
-
-static int
-select_next_protocol(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const char *key, unsigned int keylen)
-{
- unsigned int i;
- for(i = 0; i + keylen <= inlen; i += in[i] + 1) {
- if(memcmp(&in[i + 1], key, keylen) == 0) {
- *out = (unsigned char *) &in[i + 1];
- *outlen = in[i];
- return 0;
- }
- }
- return -1;
-}
-
-static int
-select_next_proto_cb(SSL *ssl,
- unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- void *arg)
-{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
- (void)ssl;
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
- !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) {
- infof(data, "NPN, negotiated HTTP2 (%s)", ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
- return SSL_TLSEXT_ERR_OK;
- }
+/* Check for OpenSSL 1.1.0 which has set_{min,max}_proto_version(). */
+#undef HAS_MODERN_SET_PROTO_VER
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L \
+ && !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20600000L)
+# define HAS_MODERN_SET_PROTO_VER 1
#endif
- if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
- ALPN_HTTP_1_1_LENGTH)) {
- infof(data, "NPN, negotiated HTTP1.1");
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- return SSL_TLSEXT_ERR_OK;
- }
-
- infof(data, "NPN, no overlap, use HTTP1.1");
- *out = (unsigned char *)ALPN_HTTP_1_1;
- *outlen = ALPN_HTTP_1_1_LENGTH;
- conn->negnpn = CURL_HTTP_VERSION_1_1;
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif /* HAS_NPN */
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
+#ifdef HAS_MODERN_SET_PROTO_VER
static CURLcode
set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
{
@@ -2424,7 +2687,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
return CURLE_OK;
}
-#endif
+#endif /* HAS_MODERN_SET_PROTO_VER */
#ifdef OPENSSL_IS_BORINGSSL
typedef uint32_t ctx_option_t;
@@ -2434,7 +2697,7 @@ typedef uint64_t ctx_option_t;
typedef long ctx_option_t;
#endif
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
+#if !defined(HAS_MODERN_SET_PROTO_VER)
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
struct Curl_easy *data,
@@ -2509,7 +2772,7 @@ set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
}
return CURLE_OK;
}
-#endif
+#endif /* ! HAS_MODERN_SET_PROTO_VER */
/* The "new session" callback must return zero if the session can be removed
* or non-zero if the session has been put into the session cache.
@@ -2813,7 +3076,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
+#if HAS_MODERN_SET_PROTO_VER /* 1.1.0 */
result = set_ssl_version_min_max(backend->ctx, conn);
#else
result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
@@ -2830,11 +3093,6 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
SSL_CTX_set_options(backend->ctx, ctx_options);
-#ifdef HAS_NPN
- if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
-#endif
-
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
int cur = 0;
@@ -2924,7 +3182,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#ifdef USE_OPENSSL_SRP
if((ssl_authtype == CURL_TLSAUTH_SRP) &&
- Curl_allow_auth_to_host(data)) {
+ Curl_auth_allowed_to_host(data)) {
char * const ssl_username = SSL_SET_OPTION(primary.username);
char * const ssl_password = SSL_SET_OPTION(primary.password);
infof(data, "Using TLS-SRP username: %s", ssl_username);
@@ -3462,19 +3720,19 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, neg_protocol, len)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
!memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -3483,342 +3741,6 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
}
}
-static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
-{
- int i, ilen;
-
- ilen = (int)len;
- if(ilen < 0)
- return 1; /* buffer too big */
-
- i = i2t_ASN1_OBJECT(buf, ilen, a);
-
- if(i >= ilen)
- return 1; /* buffer too small */
-
- return 0;
-}
-
-#define push_certinfo(_label, _num) \
-do { \
- long info_len = BIO_get_mem_data(mem, &ptr); \
- Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
- if(1 != BIO_reset(mem)) \
- break; \
-} while(0)
-
-static void pubkey_show(struct Curl_easy *data,
- BIO *mem,
- int num,
- const char *type,
- const char *name,
- const BIGNUM *bn)
-{
- char *ptr;
- char namebuf[32];
-
- msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
-
- if(bn)
- BN_print(mem, bn);
- push_certinfo(namebuf, num);
-}
-
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
-#define print_pubkey_BN(_type, _name, _num) \
- pubkey_show(data, mem, _num, #_type, #_name, _name)
-
-#else
-#define print_pubkey_BN(_type, _name, _num) \
-do { \
- if(_type->_name) { \
- pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
- } \
-} while(0)
-#endif
-
-static void X509V3_ext(struct Curl_easy *data,
- int certnum,
- CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
-{
- int i;
-
- if((int)sk_X509_EXTENSION_num(exts) <= 0)
- /* no extensions, bail out */
- return;
-
- for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
- BUF_MEM *biomem;
- char namebuf[128];
- BIO *bio_out = BIO_new(BIO_s_mem());
-
- if(!bio_out)
- return;
-
- obj = X509_EXTENSION_get_object(ext);
-
- asn1_object_dump(obj, namebuf, sizeof(namebuf));
-
- if(!X509V3_EXT_print(bio_out, ext, 0, 0))
- ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
-
- BIO_get_mem_ptr(bio_out, &biomem);
- Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
- biomem->length);
- BIO_free(bio_out);
- }
-}
-
-#ifdef OPENSSL_IS_BORINGSSL
-typedef size_t numcert_t;
-#else
-typedef int numcert_t;
-#endif
-
-static CURLcode get_cert_chain(struct Curl_easy *data,
- struct ssl_connect_data *connssl)
-{
- CURLcode result;
- STACK_OF(X509) *sk;
- int i;
- numcert_t numcerts;
- BIO *mem;
- struct ssl_backend_data *backend = connssl->backend;
-
- DEBUGASSERT(backend);
-
- sk = SSL_get_peer_cert_chain(backend->handle);
- if(!sk) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- numcerts = sk_X509_num(sk);
-
- result = Curl_ssl_init_certinfo(data, (int)numcerts);
- if(result) {
- return result;
- }
-
- mem = BIO_new(BIO_s_mem());
- if(!mem) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- for(i = 0; i < (int)numcerts; i++) {
- ASN1_INTEGER *num;
- X509 *x = sk_X509_value(sk, i);
- EVP_PKEY *pubkey = NULL;
- int j;
- char *ptr;
- const ASN1_BIT_STRING *psig = NULL;
-
- X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Subject", i);
-
- X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Issuer", i);
-
- BIO_printf(mem, "%lx", X509_get_version(x));
- push_certinfo("Version", i);
-
- num = X509_get_serialNumber(x);
- if(num->type == V_ASN1_NEG_INTEGER)
- BIO_puts(mem, "-");
- for(j = 0; j < num->length; j++)
- BIO_printf(mem, "%02x", num->data[j]);
- push_certinfo("Serial Number", i);
-
-#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
- {
- const X509_ALGOR *sigalg = NULL;
- X509_PUBKEY *xpubkey = NULL;
- ASN1_OBJECT *pubkeyoid = NULL;
-
- X509_get0_signature(&psig, &sigalg, x);
- if(sigalg) {
- i2a_ASN1_OBJECT(mem, sigalg->algorithm);
- push_certinfo("Signature Algorithm", i);
- }
-
- xpubkey = X509_get_X509_PUBKEY(x);
- if(xpubkey) {
- X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
- if(pubkeyoid) {
- i2a_ASN1_OBJECT(mem, pubkeyoid);
- push_certinfo("Public Key Algorithm", i);
- }
- }
-
- X509V3_ext(data, i, X509_get0_extensions(x));
- }
-#else
- {
- /* before OpenSSL 1.0.2 */
- X509_CINF *cinf = x->cert_info;
-
- i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
- push_certinfo("Signature Algorithm", i);
-
- i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
- push_certinfo("Public Key Algorithm", i);
-
- X509V3_ext(data, i, cinf->extensions);
-
- psig = x->signature;
- }
-#endif
-
- ASN1_TIME_print(mem, X509_get0_notBefore(x));
- push_certinfo("Start date", i);
-
- ASN1_TIME_print(mem, X509_get0_notAfter(x));
- push_certinfo("Expire date", i);
-
- pubkey = X509_get_pubkey(x);
- if(!pubkey)
- infof(data, " Unable to load public key");
- else {
- int pktype;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- pktype = EVP_PKEY_id(pubkey);
-#else
- pktype = pubkey->type;
-#endif
- switch(pktype) {
- case EVP_PKEY_RSA:
- {
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- RSA *rsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- rsa = EVP_PKEY_get0_RSA(pubkey);
-#else
- rsa = pubkey->pkey.rsa;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
-
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(n);
- DECLARE_PKEY_PARAM_BIGNUM(e);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
-#else
- RSA_get0_key(rsa, &n, &e, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- BIO_printf(mem, "%d", BN_num_bits(n));
-#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- push_certinfo("RSA Public Key", i);
- print_pubkey_BN(rsa, n, i);
- print_pubkey_BN(rsa, e, i);
- FREE_PKEY_PARAM_BIGNUM(n);
- FREE_PKEY_PARAM_BIGNUM(e);
- }
-
- break;
- }
- case EVP_PKEY_DSA:
- {
-#ifndef OPENSSL_NO_DSA
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- DSA *dsa;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dsa = EVP_PKEY_get0_DSA(pubkey);
-#else
- dsa = pubkey->pkey.dsa;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(p);
- DECLARE_PKEY_PARAM_BIGNUM(q);
- DECLARE_PKEY_PARAM_BIGNUM(g);
- DECLARE_PKEY_PARAM_BIGNUM(pub_key);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
-#else
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- print_pubkey_BN(dsa, p, i);
- print_pubkey_BN(dsa, q, i);
- print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, pub_key, i);
- FREE_PKEY_PARAM_BIGNUM(p);
- FREE_PKEY_PARAM_BIGNUM(q);
- FREE_PKEY_PARAM_BIGNUM(g);
- FREE_PKEY_PARAM_BIGNUM(pub_key);
- }
-#endif /* !OPENSSL_NO_DSA */
- break;
- }
- case EVP_PKEY_DH:
- {
-#ifndef HAVE_EVP_PKEY_GET_PARAMS
- DH *dh;
-#ifdef HAVE_OPAQUE_EVP_PKEY
- dh = EVP_PKEY_get0_DH(pubkey);
-#else
- dh = pubkey->pkey.dh;
-#endif /* HAVE_OPAQUE_EVP_PKEY */
-#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
- {
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
- DECLARE_PKEY_PARAM_BIGNUM(p);
- DECLARE_PKEY_PARAM_BIGNUM(q);
- DECLARE_PKEY_PARAM_BIGNUM(g);
- DECLARE_PKEY_PARAM_BIGNUM(pub_key);
-#ifdef HAVE_EVP_PKEY_GET_PARAMS
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
- EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
-#else
- DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, NULL);
-#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, q, i);
- print_pubkey_BN(dh, g, i);
-#else
- print_pubkey_BN(dh, p, i);
- print_pubkey_BN(dh, g, i);
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- print_pubkey_BN(dh, pub_key, i);
- FREE_PKEY_PARAM_BIGNUM(p);
- FREE_PKEY_PARAM_BIGNUM(q);
- FREE_PKEY_PARAM_BIGNUM(g);
- FREE_PKEY_PARAM_BIGNUM(pub_key);
- }
- break;
- }
- }
- EVP_PKEY_free(pubkey);
- }
-
- if(psig) {
- for(j = 0; j < psig->length; j++)
- BIO_printf(mem, "%02x:", psig->data[j]);
- push_certinfo("Signature", i);
- }
-
- PEM_write_bio_X509(mem, x);
- push_certinfo("Cert", i);
- }
-
- BIO_free(mem);
-
- return CURLE_OK;
-}
-
/*
* Heavily modified from:
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
@@ -3913,8 +3835,8 @@ static CURLcode servercert(struct Curl_easy *data,
}
if(data->set.ssl.certinfo)
- /* we've been asked to gather certificate info! */
- (void)get_cert_chain(data, connssl);
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, connssl->backend->handle);
backend->server_cert = SSL_get1_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -4457,7 +4379,7 @@ static size_t ossl_version(char *buffer, size_t size)
}
count = msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
for(p = buffer; *p; ++p) {
- if(ISSPACE(*p))
+ if(ISBLANK(*p))
*p = '_';
}
return count;
@@ -4469,7 +4391,13 @@ static size_t ossl_version(char *buffer, size_t size)
(LIBRESSL_VERSION_NUMBER>>12)&0xff);
#endif
#elif defined(OPENSSL_IS_BORINGSSL)
+#ifdef CURL_BORINGSSL_VERSION
+ return msnprintf(buffer, size, "%s/%s",
+ OSSL_PACKAGE,
+ CURL_BORINGSSL_VERSION);
+#else
return msnprintf(buffer, size, OSSL_PACKAGE);
+#endif
#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING)
return msnprintf(buffer, size, "%s/%s",
OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index 0a7536ea3..9df4ecddb 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -29,6 +31,7 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ssl.h>
#include "urldata.h"
@@ -51,5 +54,7 @@ CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
const struct curl_blob *key_blob,
const char *key_type, char *key_passwd);
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
index 16970b7c3..77a49f1ab 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.c
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -413,20 +415,20 @@ cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_HTTP_1_1);
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
else {
infof(data, "ALPN, negotiated an unrecognized protocol");
}
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
diff --git a/Utilities/cmcurl/lib/vtls/rustls.h b/Utilities/cmcurl/lib/vtls/rustls.h
index 056211dd8..6b393dd63 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.h
+++ b/Utilities/cmcurl/lib/vtls/rustls.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews,
+ * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#ifndef HEADER_CURL_RUSTLS_H
#define HEADER_CURL_RUSTLS_H
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index dfec66d51..e022a2ce8 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -51,6 +53,7 @@
#include "curl_printf.h"
#include "multiif.h"
#include "version_win32.h"
+#include "rand.h"
/* The last #include file should be: */
#include "curl_memory.h"
@@ -81,8 +84,35 @@
#endif
#endif
-#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
-#define HAS_CLIENT_CERT_PATH
+#ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
+#define BCRYPT_CHACHA20_POLY1305_ALGORITHM L"CHACHA20_POLY1305"
+#endif
+
+#ifndef BCRYPT_CHAIN_MODE_CCM
+#define BCRYPT_CHAIN_MODE_CCM L"ChainingModeCCM"
+#endif
+
+#ifndef BCRYPT_CHAIN_MODE_GCM
+#define BCRYPT_CHAIN_MODE_GCM L"ChainingModeGCM"
+#endif
+
+#ifndef BCRYPT_AES_ALGORITHM
+#define BCRYPT_AES_ALGORITHM L"AES"
+#endif
+
+#ifndef BCRYPT_SHA256_ALGORITHM
+#define BCRYPT_SHA256_ALGORITHM L"SHA256"
+#endif
+
+#ifndef BCRYPT_SHA384_ALGORITHM
+#define BCRYPT_SHA384_ALGORITHM L"SHA384"
+#endif
+
+/* Workaround broken compilers like MinGW.
+ Return the number of elements in a statically sized array.
+*/
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#ifdef HAS_CLIENT_CERT_PATH
@@ -117,6 +147,10 @@
#define SP_PROT_TLS1_2_CLIENT 0x00000800
#endif
+#ifndef SP_PROT_TLS1_3_CLIENT
+#define SP_PROT_TLS1_3_CLIENT 0x00002000
+#endif
+
#ifndef SCH_USE_STRONG_CRYPTO
#define SCH_USE_STRONG_CRYPTO 0x00400000
#endif
@@ -147,6 +181,10 @@
#define ALG_CLASS_DHASH ALG_CLASS_HASH
#endif
+#ifndef PKCS12_NO_PERSIST_KEY
+#define PKCS12_NO_PERSIST_KEY 0x00008000
+#endif
+
static Curl_recv schannel_recv;
static Curl_send schannel_send;
@@ -171,7 +209,7 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
-set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
+set_ssl_version_min_max(DWORD *enabled_protocols, struct Curl_easy *data,
struct connectdata *conn)
{
long ssl_version = SSL_CONN_CONFIG(version);
@@ -181,23 +219,51 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+
+#if 0 /* Disabled in CMake due to issue 24147 (curl issue 9431) */
+ /* Windows Server 2022 and newer (including Windows 11) support TLS 1.3
+ built-in. Previous builds of Windows 10 had broken TLS 1.3
+ implementations that could be enabled via registry.
+ */
+ if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+ }
+ else /* Windows 10 and older */
+#endif
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+
break;
}
+
for(; i <= (ssl_version_max >> 16); ++i) {
switch(i) {
case CURL_SSLVERSION_TLSv1_0:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_0_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_1:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_1_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_2:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_3:
+
+#if 0 /* Disabled in CMake due to issue 24147 (curl issue 9431) */
+ /* Windows Server 2022 and newer */
+ if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ (*enabled_protocols) |= SP_PROT_TLS1_3_CLIENT;
+ break;
+ }
+ else { /* Windows 10 and older */
+ failf(data, "schannel: TLS 1.3 not supported on Windows prior to 11");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#else
failf(data, "schannel: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
}
}
return CURLE_OK;
@@ -214,8 +280,12 @@ get_alg_id_by_name(char *name)
{
char tmp[LONGEST_ALG_ID] = { 0 };
char *nameEnd = strchr(name, ':');
- size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
- min(strlen(name), LONGEST_ALG_ID - 1);
+ size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name);
+
+ /* reject too-long alg names */
+ if(n > (LONGEST_ALG_ID - 1))
+ return 0;
+
strncpy(tmp, name, n);
tmp[n] = 0;
CIPHEROPTION(CALG_MD2);
@@ -383,13 +453,13 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
else if(_tcsncmp(path, TEXT("Users"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_USERS;
else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"),
- store_name_len) == 0)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"),
- store_name_len) == 0)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"),
- store_name_len) == 0)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else
return CURLE_SSL_CERTPROBLEM;
@@ -419,49 +489,52 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SCHANNEL_CRED schannel_cred;
- ALG_ID algIds[NUM_CIPHERS];
+
+#ifdef HAS_CLIENT_CERT_PATH
PCCERT_CONTEXT client_certs[1] = { NULL };
+ HCERTSTORE client_cert_store = NULL;
+#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
+
+ /* setup Schannel API options */
+ DWORD flags = 0;
+ DWORD enabled_protocols = 0;
+
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(backend);
- /* setup Schannel API options */
- memset(&schannel_cred, 0, sizeof(schannel_cred));
- schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
-
if(conn->ssl_config.verifypeer) {
#ifdef HAS_MANUAL_VERIFY_API
if(backend->use_manual_cred_validation)
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ flags = SCH_CRED_MANUAL_CRED_VALIDATION;
else
#endif
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+ flags = SCH_CRED_AUTO_CRED_VALIDATION;
if(SSL_SET_OPTION(no_revoke)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
DEBUGF(infof(data, "schannel: disabled server certificate revocation "
"checks"));
}
else if(SSL_SET_OPTION(revoke_best_effort)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
DEBUGF(infof(data, "schannel: ignore revocation offline errors"));
}
else {
- schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
+ flags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
DEBUGF(infof(data,
"schannel: checking server certificate revocation"));
}
}
else {
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ flags = SCH_CRED_MANUAL_CRED_VALIDATION |
SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
DEBUGF(infof(data,
@@ -469,15 +542,15 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
}
if(!conn->ssl_config.verifyhost) {
- schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
+ flags |= SCH_CRED_NO_SERVERNAME_CHECK;
DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from "
"comparing the supplied target name with the subject "
"names in server certificates."));
}
if(!SSL_SET_OPTION(auto_client_cert)) {
- schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
- schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ flags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ flags |= SCH_CRED_NO_DEFAULT_CREDS;
infof(data, "schannel: disabled automatic use of client certificate");
}
else
@@ -491,7 +564,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- result = set_ssl_version_min_max(&schannel_cred, data, conn);
+ result = set_ssl_version_min_max(&enabled_protocols, data, conn);
if(result != CURLE_OK)
return result;
break;
@@ -505,16 +578,6 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if(SSL_CONN_CONFIG(cipher_list)) {
- result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
- algIds);
- if(CURLE_OK != result) {
- failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
- return result;
- }
- }
-
-
#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
@@ -540,7 +603,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
result = get_cert_location(cert_path, &cert_store_name,
- &cert_store_path, &cert_thumbprint_str);
+ &cert_store_path, &cert_thumbprint_str);
if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
@@ -555,18 +618,18 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
}
if((fInCert || blob) && (data->set.ssl.cert_type) &&
- (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
+ (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
failf(data, "schannel: certificate format compatibility error "
- " for %s",
- blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
+ " for %s",
+ blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
if(fInCert || blob) {
/* Reading a .P12 or .pfx file, like the example at bottom of
- https://social.msdn.microsoft.com/Forums/windowsdesktop/
- en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
+ https://social.msdn.microsoft.com/Forums/windowsdesktop/
+ en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
*/
CRYPT_DATA_BLOB datablob;
WCHAR* pszPassword;
@@ -594,7 +657,7 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
fclose(fInCert);
if(!continue_reading) {
failf(data, "schannel: Failed to read cert file %s",
- data->set.ssl.primary.clientcert);
+ data->set.ssl.primary.clientcert);
free(certdata);
return CURLE_SSL_CERTPROBLEM;
}
@@ -610,16 +673,23 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
if(pszPassword) {
if(pwd_len > 0)
str_w_len = MultiByteToWideChar(CP_UTF8,
- MB_ERR_INVALID_CHARS,
- data->set.ssl.key_passwd, (int)pwd_len,
- pszPassword, (int)(pwd_len + 1));
+ MB_ERR_INVALID_CHARS,
+ data->set.ssl.key_passwd,
+ (int)pwd_len,
+ pszPassword, (int)(pwd_len + 1));
if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
pszPassword[str_w_len] = 0;
else
pszPassword[0] = 0;
- cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+ if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ cert_store = PFXImportCertStore(&datablob, pszPassword,
+ PKCS12_NO_PERSIST_KEY);
+ else
+ cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+
free(pszPassword);
}
if(!blob)
@@ -648,9 +718,6 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
-
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
}
else {
cert_store =
@@ -688,17 +755,13 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
curlx_unicodefree(cert_path);
- if(client_certs[0]) {
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
- }
- else {
+ if(!client_certs[0]) {
/* CRYPT_E_NOT_FOUND / E_INVALIDARG */
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
}
- CertCloseStore(cert_store, 0);
+ client_cert_store = cert_store;
}
#else
if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
@@ -713,22 +776,279 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
if(!backend->cred) {
failf(data, "schannel: unable to allocate memory");
+#ifdef HAS_CLIENT_CERT_PATH
if(client_certs[0])
CertFreeCertificateContext(client_certs[0]);
+ if(client_cert_store)
+ CertCloseStore(client_cert_store, 0);
+#endif
return CURLE_OUT_OF_MEMORY;
}
backend->cred->refcount = 1;
- sspi_status =
- s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
- SECPKG_CRED_OUTBOUND, NULL,
- &schannel_cred, NULL, NULL,
- &backend->cred->cred_handle,
- &backend->cred->time_stamp);
+#ifdef HAS_CLIENT_CERT_PATH
+ /* Since we did not persist the key, we need to extend the store's
+ * lifetime until the end of the connection
+ */
+ backend->cred->client_cert_store = client_cert_store;
+#endif
+
+ /* Windows 10, 1809 (a.k.a. Windows 10 build 17763) */
+ if(curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+
+ char *ciphers13 = 0;
+
+ bool disable_aes_gcm_sha384 = FALSE;
+ bool disable_aes_gcm_sha256 = FALSE;
+ bool disable_chacha_poly = FALSE;
+ bool disable_aes_ccm_8_sha256 = FALSE;
+ bool disable_aes_ccm_sha256 = FALSE;
+
+ SCH_CREDENTIALS credentials = { 0 };
+ TLS_PARAMETERS tls_parameters = { 0 };
+ CRYPTO_SETTINGS crypto_settings[4] = { 0 };
+ UNICODE_STRING blocked_ccm_modes[1] = { 0 };
+ UNICODE_STRING blocked_gcm_modes[1] = { 0 };
+ int crypto_settings_idx = 0;
+
+
+ /* If TLS 1.3 ciphers are explicitly listed, then
+ * disable all the ciphers and re-enable which
+ * ciphers the user has provided.
+ */
+ ciphers13 = SSL_CONN_CONFIG(cipher_list13);
+ if(ciphers13) {
+ const int remaining_ciphers = 5;
+
+ /* detect which remaining ciphers to enable
+ and then disable everything else.
+ */
+
+ char *startCur = ciphers13;
+ int algCount = 0;
+ char tmp[LONGEST_ALG_ID] = { 0 };
+ char *nameEnd;
+ size_t n;
+
+ disable_aes_gcm_sha384 = TRUE;
+ disable_aes_gcm_sha256 = TRUE;
+ disable_chacha_poly = TRUE;
+ disable_aes_ccm_8_sha256 = TRUE;
+ disable_aes_ccm_sha256 = TRUE;
+
+ while(startCur && (0 != *startCur) && (algCount < remaining_ciphers)) {
+ nameEnd = strchr(startCur, ':');
+ n = nameEnd ? (size_t)(nameEnd - startCur) : strlen(startCur);
+
+ /* reject too-long cipher names */
+ if(n > (LONGEST_ALG_ID - 1)) {
+ failf(data, "Cipher name too long, not checked.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ strncpy(tmp, startCur, n);
+ tmp[n] = 0;
+
+ if(disable_aes_gcm_sha384
+ && !strcmp("TLS_AES_256_GCM_SHA384", tmp)) {
+ disable_aes_gcm_sha384 = FALSE;
+ }
+ else if(disable_aes_gcm_sha256
+ && !strcmp("TLS_AES_128_GCM_SHA256", tmp)) {
+ disable_aes_gcm_sha256 = FALSE;
+ }
+ else if(disable_chacha_poly
+ && !strcmp("TLS_CHACHA20_POLY1305_SHA256", tmp)) {
+ disable_chacha_poly = FALSE;
+ }
+ else if(disable_aes_ccm_8_sha256
+ && !strcmp("TLS_AES_128_CCM_8_SHA256", tmp)) {
+ disable_aes_ccm_8_sha256 = FALSE;
+ }
+ else if(disable_aes_ccm_sha256
+ && !strcmp("TLS_AES_128_CCM_SHA256", tmp)) {
+ disable_aes_ccm_sha256 = FALSE;
+ }
+ else {
+ failf(data, "Passed in an unknown TLS 1.3 cipher.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ startCur = nameEnd;
+ if(startCur)
+ startCur++;
+
+ algCount++;
+ }
+ }
+
+ if(disable_aes_gcm_sha384 && disable_aes_gcm_sha256
+ && disable_chacha_poly && disable_aes_ccm_8_sha256
+ && disable_aes_ccm_sha256) {
+ failf(data, "All available TLS 1.3 ciphers were disabled.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ /* Disable TLS_AES_128_CCM_8_SHA256 and/or TLS_AES_128_CCM_SHA256 */
+ if(disable_aes_ccm_8_sha256 || disable_aes_ccm_sha256) {
+ /*
+ Disallow AES_CCM algorithm.
+ */
+ blocked_ccm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_CCM);
+ blocked_ccm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_CCM);
+ blocked_ccm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_CCM;
+
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].rgstrChainingModes =
+ blocked_ccm_modes;
+ crypto_settings[crypto_settings_idx].cChainingModes =
+ ARRAYSIZE(blocked_ccm_modes);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_AES_ALGORITHM;
+
+ /* only disabling one of the CCM modes */
+ if(disable_aes_ccm_8_sha256 != disable_aes_ccm_sha256) {
+ if(disable_aes_ccm_8_sha256)
+ crypto_settings[crypto_settings_idx].dwMinBitLength = 128;
+ else /* disable_aes_ccm_sha256 */
+ crypto_settings[crypto_settings_idx].dwMaxBitLength = 64;
+ }
+
+ crypto_settings_idx++;
+ }
+
+ /* Disable TLS_AES_256_GCM_SHA384 and/or TLS_AES_128_GCM_SHA256 */
+ if(disable_aes_gcm_sha384 || disable_aes_gcm_sha256) {
+
+ /*
+ Disallow AES_GCM algorithm
+ */
+ blocked_gcm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_GCM);
+ blocked_gcm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_GCM);
+ blocked_gcm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_GCM;
+
+ /* if only one is disabled, then explicitly disable the
+ digest cipher suite (sha384 or sha256) */
+ if(disable_aes_gcm_sha384 != disable_aes_gcm_sha256) {
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageDigest;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ }
+ else { /* Disable both AES_GCM ciphers */
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_AES_ALGORITHM;
+ }
+
+ crypto_settings[crypto_settings_idx].rgstrChainingModes =
+ blocked_gcm_modes;
+ crypto_settings[crypto_settings_idx].cChainingModes = 1;
+
+ crypto_settings_idx++;
+ }
+
+ /*
+ Disable ChaCha20-Poly1305.
+ */
+ if(disable_chacha_poly) {
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_CHACHA20_POLY1305_ALGORITHM;
+ crypto_settings_idx++;
+ }
+
+ tls_parameters.pDisabledCrypto = crypto_settings;
+
+ /* The number of blocked suites */
+ tls_parameters.cDisabledCrypto = crypto_settings_idx;
+ credentials.pTlsParameters = &tls_parameters;
+ credentials.cTlsParameters = 1;
+
+ credentials.dwVersion = SCH_CREDENTIALS_VERSION;
+ credentials.dwFlags = flags | SCH_USE_STRONG_CRYPTO;
+
+ credentials.pTlsParameters->grbitDisabledProtocols =
+ (DWORD)~enabled_protocols;
+
+#ifdef HAS_CLIENT_CERT_PATH
+ if(client_certs[0]) {
+ credentials.cCreds = 1;
+ credentials.paCred = client_certs;
+ }
+#endif
+
+ sspi_status =
+ s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL,
+ &credentials, NULL, NULL,
+ &backend->cred->cred_handle,
+ &backend->cred->time_stamp);
+ }
+ else {
+ /* Pre-Windows 10 1809 */
+ ALG_ID algIds[NUM_CIPHERS];
+ char *ciphers = SSL_CONN_CONFIG(cipher_list);
+ SCHANNEL_CRED schannel_cred = { 0 };
+ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
+ schannel_cred.dwFlags = flags;
+ schannel_cred.grbitEnabledProtocols = enabled_protocols;
+
+ if(ciphers) {
+ result = set_ssl_ciphers(&schannel_cred, ciphers, algIds);
+ if(CURLE_OK != result) {
+ failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+ return result;
+ }
+ }
+ else {
+ schannel_cred.dwFlags = flags | SCH_USE_STRONG_CRYPTO;
+ }
+
+#ifdef HAS_CLIENT_CERT_PATH
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+#endif
+
+ sspi_status =
+ s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL,
+ &schannel_cred, NULL, NULL,
+ &backend->cred->cred_handle,
+ &backend->cred->time_stamp);
+ }
+
+#ifdef HAS_CLIENT_CERT_PATH
if(client_certs[0])
CertFreeCertificateContext(client_certs[0]);
+#endif
if(sspi_status != SEC_E_OK) {
char buffer[STRERROR_LEN];
@@ -1016,6 +1336,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
backend->recv_unrecoverable_err = CURLE_OK;
backend->recv_sspi_close_notify = false;
backend->recv_connection_closed = false;
+ backend->recv_renegotiating = false;
backend->encdata_is_incomplete = false;
/* continue to second handshake step */
@@ -1415,6 +1736,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(alpn_result.ProtoNegoStatus ==
SecApplicationProtocolNegotiationStatus_Success) {
+ unsigned char alpn = 0;
infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR,
alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
@@ -1422,20 +1744,33 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
!memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ alpn = CURL_HTTP_VERSION_1_1;
}
+ if(backend->recv_renegotiating) {
+ if(alpn != conn->alpn) {
+ failf(data, "schannel: server selected an ALPN protocol too late");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else
+ conn->alpn = alpn;
+ }
+ else {
+ if(!backend->recv_renegotiating)
+ infof(data, VTLS_INFOF_NO_ALPN);
+ }
+
+ if(!backend->recv_renegotiating) {
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
+ BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
- else
- infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -1607,8 +1942,15 @@ schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = schannel_recv;
- conn->send[sockindex] = schannel_send;
+ if(!connssl->backend->recv_renegotiating) {
+ /* On renegotiation, we don't want to reset the existing recv/send
+ * function pointers. They will have been set after the initial TLS
+ * handshake was completed. If they were subsequently modified, as
+ * is the case with HTTP/2, we don't want to override that change.
+ */
+ conn->recv[sockindex] = schannel_recv;
+ conn->send[sockindex] = schannel_send;
+ }
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
/* When SSPI is used in combination with Schannel
@@ -1990,17 +2332,14 @@ schannel_recv(struct Curl_easy *data, int sockindex,
infof(data, "schannel: can't renegotiate, an error is pending");
goto cleanup;
}
- if(backend->encdata_offset) {
- *err = CURLE_RECV_ERROR;
- infof(data, "schannel: can't renegotiate, "
- "encrypted data available");
- goto cleanup;
- }
+
/* begin renegotiation */
infof(data, "schannel: renegotiating SSL/TLS connection");
connssl->state = ssl_connection_negotiating;
connssl->connecting_state = ssl_connect_2_writing;
+ backend->recv_renegotiating = true;
*err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
+ backend->recv_renegotiating = false;
if(*err) {
infof(data, "schannel: renegotiation failed");
goto cleanup;
@@ -2154,6 +2493,12 @@ static void schannel_session_free(void *ptr)
if(cred->refcount == 0) {
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
curlx_unicodefree(cred->sni_hostname);
+#ifdef HAS_CLIENT_CERT_PATH
+ if(cred->client_cert_store) {
+ CertCloseStore(cred->client_cert_store, 0);
+ cred->client_cert_store = NULL;
+ }
+#endif
Curl_safefree(cred);
}
}
@@ -2296,21 +2641,9 @@ static size_t schannel_version(char *buffer, size_t size)
static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
unsigned char *entropy, size_t length)
{
- HCRYPTPROV hCryptProv = 0;
-
(void)data;
- if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- return CURLE_FAILED_INIT;
-
- if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
- CryptReleaseContext(hCryptProv, 0UL);
- return CURLE_FAILED_INIT;
- }
-
- CryptReleaseContext(hCryptProv, 0UL);
- return CURLE_OK;
+ return Curl_win32_random(entropy, length);
}
static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
@@ -2457,7 +2790,8 @@ const struct Curl_ssl Curl_ssl_schannel = {
#ifdef HAS_MANUAL_VERIFY_API
SSLSUPP_CAINFO_BLOB |
#endif
- SSLSUPP_PINNEDPUBKEY,
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_TLS13_CIPHERSUITES,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index da6070277..24d7eff25 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -21,11 +21,35 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_SCHANNEL
+#define SCHANNEL_USE_BLACKLISTS 1
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4201)
+#endif
+#include <subauth.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
#include <schnlsp.h>
#include <schannel.h>
#include "curl_sspi.h"
@@ -59,22 +83,87 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+#include <wincrypt.h>
+
#ifdef __MINGW32__
-#include <_mingw.h>
#ifdef __MINGW64_VERSION_MAJOR
#define HAS_MANUAL_VERIFY_API
#endif
#else
-#include <wincrypt.h>
#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
#define HAS_MANUAL_VERIFY_API
#endif
#endif
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
+ && !defined(DISABLE_SCHANNEL_CLIENT_CERT)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifndef SCH_CREDENTIALS_VERSION
+
+#define SCH_CREDENTIALS_VERSION 0x00000005
+
+typedef enum _eTlsAlgorithmUsage
+{
+ TlsParametersCngAlgUsageKeyExchange,
+ TlsParametersCngAlgUsageSignature,
+ TlsParametersCngAlgUsageCipher,
+ TlsParametersCngAlgUsageDigest,
+ TlsParametersCngAlgUsageCertSig
+} eTlsAlgorithmUsage;
+
+typedef struct _CRYPTO_SETTINGS
+{
+ eTlsAlgorithmUsage eAlgorithmUsage;
+ UNICODE_STRING strCngAlgId;
+ DWORD cChainingModes;
+ PUNICODE_STRING rgstrChainingModes;
+ DWORD dwMinBitLength;
+ DWORD dwMaxBitLength;
+} CRYPTO_SETTINGS, * PCRYPTO_SETTINGS;
+
+typedef struct _TLS_PARAMETERS
+{
+ DWORD cAlpnIds;
+ PUNICODE_STRING rgstrAlpnIds;
+ DWORD grbitDisabledProtocols;
+ DWORD cDisabledCrypto;
+ PCRYPTO_SETTINGS pDisabledCrypto;
+ DWORD dwFlags;
+} TLS_PARAMETERS, * PTLS_PARAMETERS;
+
+typedef struct _SCH_CREDENTIALS
+{
+ DWORD dwVersion;
+ DWORD dwCredFormat;
+ DWORD cCreds;
+ PCCERT_CONTEXT* paCred;
+ HCERTSTORE hRootStore;
+
+ DWORD cMappers;
+ struct _HMAPPER **aphMappers;
+
+ DWORD dwSessionLifespan;
+ DWORD dwFlags;
+ DWORD cTlsParameters;
+ PTLS_PARAMETERS pTlsParameters;
+} SCH_CREDENTIALS, * PSCH_CREDENTIALS;
+
+#define SCH_CRED_MAX_SUPPORTED_PARAMETERS 16
+#define SCH_CRED_MAX_SUPPORTED_ALPN_IDS 16
+#define SCH_CRED_MAX_SUPPORTED_CRYPTO_SETTINGS 16
+#define SCH_CRED_MAX_SUPPORTED_CHAINING_MODES 16
+
+#endif
+
struct Curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
TCHAR *sni_hostname;
+#ifdef HAS_CLIENT_CERT_PATH
+ HCERTSTORE client_cert_store;
+#endif
int refcount;
};
@@ -99,6 +188,7 @@ struct ssl_backend_data {
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool recv_renegotiating; /* true if recv is doing renegotiation */
bool use_alpn; /* true if ALPN is used for this connection */
#ifdef HAS_MANUAL_VERIFY_API
bool use_manual_cred_validation; /* true if manual cred validation is used */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index 4dc2d14e5..1ac1d3eaf 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 2e57d8378..c764e3631 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -2845,18 +2847,18 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
@@ -2964,7 +2966,7 @@ collect_server_cert(struct Curl_easy *data,
private API and doesn't work as expected. So we have to look for
a different symbol to make sure this code is only executed under
Lion or later. */
- if(SecTrustEvaluateAsync) {
+ if(SecTrustCopyPublicKey) {
#pragma unused(server_certs)
err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
/* For some reason, SSLCopyPeerTrust() can return noErr and yet return
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.h b/Utilities/cmcurl/lib/vtls/sectransp.h
index 0febd6613..2d53b7c48 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.h
+++ b/Utilities/cmcurl/lib/vtls/sectransp.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index e2d34388c..9dee5aa3b 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/* This file is for implementing all "generic" SSL functions that all libcurl
@@ -143,11 +145,9 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safecmp(data->CAfile, needle->CAfile) &&
Curl_safecmp(data->issuercert, needle->issuercert) &&
Curl_safecmp(data->clientcert, needle->clientcert) &&
- Curl_safecmp(data->random_file, needle->random_file) &&
- Curl_safecmp(data->egdsocket, needle->egdsocket) &&
#ifdef USE_TLS_SRP
- Curl_safecmp(data->username, needle->username) &&
- Curl_safecmp(data->password, needle->password) &&
+ !Curl_timestrcmp(data->username, needle->username) &&
+ !Curl_timestrcmp(data->password, needle->password) &&
(data->authtype == needle->authtype) &&
#endif
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
@@ -182,8 +182,6 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(CAfile);
CLONE_STRING(issuercert);
CLONE_STRING(clientcert);
- CLONE_STRING(random_file);
- CLONE_STRING(egdsocket);
CLONE_STRING(cipher_list);
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
@@ -203,8 +201,6 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->issuercert);
Curl_safefree(sslc->clientcert);
- Curl_safefree(sslc->random_file);
- Curl_safefree(sslc->egdsocket);
Curl_safefree(sslc->cipher_list);
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
@@ -223,13 +219,13 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
static int multissl_setup(const struct Curl_ssl *backend);
#endif
-int Curl_ssl_backend(void)
+curl_sslbackend Curl_ssl_backend(void)
{
#ifdef USE_SSL
multissl_setup(NULL);
return Curl_ssl->info.id;
#else
- return (int)CURLSSLBACKEND_NONE;
+ return CURLSSLBACKEND_NONE;
#endif
}
@@ -903,7 +899,7 @@ char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen)
size_t len = strlen(host);
if(len && (host[len-1] == '.'))
len--;
- if((long)len >= data->set.buffer_size)
+ if(len >= data->set.buffer_size)
return NULL;
Curl_strntolower(data->state.buffer, host, len);
@@ -1460,8 +1456,10 @@ static int multissl_setup(const struct Curl_ssl *backend)
return 0;
}
-CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
- const curl_ssl_backend ***avail)
+/* This function is used to select the SSL backend to use. It is called by
+ curl_global_sslset (easy.c) which uses the global init lock. */
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
{
int i;
@@ -1490,8 +1488,8 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
}
#else /* USE_SSL */
-CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
- const curl_ssl_backend ***avail)
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
{
(void)id;
(void)name;
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 6bd1e0dcd..50c53b3fb 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -123,6 +125,9 @@ struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
bool Curl_ssl_tls13_ciphersuites(void);
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail);
+
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
@@ -195,7 +200,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
ssl_connect_2_writing. */
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
-int Curl_ssl_backend(void);
+curl_sslbackend Curl_ssl_backend(void);
#ifdef USE_SSL
int Curl_ssl_init(void);
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index da8cb82ce..594c39a32 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
/*
@@ -503,7 +505,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
SSL_free(backend->handle);
backend->handle = SSL_new(backend->ctx);
if(!backend->handle) {
- failf(data, "SSL: couldn't create a context");
+ failf(data, "SSL: couldn't create a handle");
return CURLE_OUT_OF_MEMORY;
}
@@ -761,17 +763,17 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
!memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ conn->alpn = CURL_HTTP_VERSION_1_1;
#ifdef USE_HTTP2
else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
protocol_len == ALPN_H2_LENGTH &&
!memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_2;
+ conn->alpn = CURL_HTTP_VERSION_2;
#endif
else
infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else if(rc == SSL_ALPN_NOT_FOUND)
@@ -809,8 +811,10 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
+ bool added = FALSE;
void *old_ssl_sessionid = NULL;
- SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
+ /* SSL_get1_session allocates memory that has to be freed. */
+ SSL_SESSION *our_ssl_sessionid = SSL_get1_session(backend->handle);
bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
if(our_ssl_sessionid) {
@@ -830,11 +834,20 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
0, sockindex, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
+ SSL_SESSION_free(our_ssl_sessionid);
failf(data, "failed to store ssl session");
return result;
}
+ else {
+ added = TRUE;
+ }
}
Curl_ssl_sessionid_unlock(data);
+
+ if(!added) {
+ /* If the session info wasn't added to the cache, free our copy. */
+ SSL_SESSION_free(our_ssl_sessionid);
+ }
}
}
@@ -954,8 +967,7 @@ static ssize_t wolfssl_recv(struct Curl_easy *data,
static void wolfssl_session_free(void *ptr)
{
- (void)ptr;
- /* wolfSSL reuses sessions on own, no free */
+ SSL_SESSION_free(ptr);
}
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.h b/Utilities/cmcurl/lib/vtls/wolfssl.h
index d411e6913..b2e7c3fde 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.h
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/vtls/x509asn1.c b/Utilities/cmcurl/lib/vtls/x509asn1.c
index dfb938621..0cfcbe87d 100644
--- a/Utilities/cmcurl/lib/vtls/x509asn1.c
+++ b/Utilities/cmcurl/lib/vtls/x509asn1.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -43,6 +45,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "strcase.h"
+#include "curl_ctype.h"
#include "hostcheck.h"
#include "vtls/vtls.h"
#include "sendf.h"
@@ -714,7 +717,7 @@ static ssize_t encodeDN(char *buf, size_t buflen, struct Curl_asn1Element *dn)
/* Encode delimiter.
If attribute has a short uppercase name, delimiter is ", ". */
if(l) {
- for(p3 = str; isupper(*p3); p3++)
+ for(p3 = str; ISUPPER(*p3); p3++)
;
for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
if(l < buflen)
@@ -956,7 +959,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
infof(data, " ECC Public Key (%lu bits)", len);
if(data->set.ssl.certinfo) {
char q[sizeof(len) * 8 / 3 + 1];
- msnprintf(q, sizeof(q), "%lu", len);
+ (void)msnprintf(q, sizeof(q), "%lu", len);
if(Curl_ssl_push_certinfo(data, certnum, "ECC Public Key", q))
return 1;
}
diff --git a/Utilities/cmcurl/lib/vtls/x509asn1.h b/Utilities/cmcurl/lib/vtls/x509asn1.h
index db7df0ef1..a18fa1153 100644
--- a/Utilities/cmcurl/lib/vtls/x509asn1.h
+++ b/Utilities/cmcurl/lib/vtls/x509asn1.h
@@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index 0336a41d8..b00d7a5a2 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
@@ -37,6 +39,8 @@
#include "warnless.h"
+#include <limits.h>
+
#define CURL_MASK_UCHAR ((unsigned char)~0)
#define CURL_MASK_SCHAR (CURL_MASK_UCHAR >> 1)
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index 37ac5ba19..4367099d9 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index 105bcce4e..a3e24b678 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 081be9ed9..21e933b9a 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,11 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
+ * SPDX-License-Identifier: curl
+ *
***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DISABLE_FTP
+#include <curl/curl.h>
#include "llist.h"
/* list of wildcard process states */
diff --git a/Utilities/cmcurl/lib/ws.c b/Utilities/cmcurl/lib/ws.c
new file mode 100644
index 000000000..a67344662
--- /dev/null
+++ b/Utilities/cmcurl/lib/ws.c
@@ -0,0 +1,757 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include <curl/curl.h>
+
+#ifdef USE_WEBSOCKETS
+
+#include "urldata.h"
+#include "dynbuf.h"
+#include "rand.h"
+#include "curl_base64.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "ws.h"
+#include "easyif.h"
+#include "transfer.h"
+#include "nonblock.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+struct wsfield {
+ const char *name;
+ const char *val;
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req)
+{
+ unsigned int i;
+ CURLcode result = CURLE_OK;
+ unsigned char rand[16];
+ char *randstr;
+ size_t randlen;
+ char keyval[40];
+ struct SingleRequest *k = &data->req;
+ struct wsfield heads[]= {
+ {
+ /* The request MUST contain an |Upgrade| header field whose value
+ MUST include the "websocket" keyword. */
+ "Upgrade:", "websocket"
+ },
+ {
+ /* The request MUST contain a |Connection| header field whose value
+ MUST include the "Upgrade" token. */
+ "Connection:", "Upgrade",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Version|. The value of this header field MUST be
+ 13. */
+ "Sec-WebSocket-Version:", "13",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Key|. The value of this header field MUST be a nonce
+ consisting of a randomly selected 16-byte value that has been
+ base64-encoded (see Section 4 of [RFC4648]). The nonce MUST be
+ selected randomly for each connection. */
+ "Sec-WebSocket-Key:", NULL,
+ }
+ };
+ heads[3].val = &keyval[0];
+
+ /* 16 bytes random */
+ result = Curl_rand(data, (unsigned char *)rand, sizeof(rand));
+ if(result)
+ return result;
+ result = Curl_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen);
+ if(result)
+ return result;
+ DEBUGASSERT(randlen < sizeof(keyval));
+ if(randlen >= sizeof(keyval))
+ return CURLE_FAILED_INIT;
+ strcpy(keyval, randstr);
+ free(randstr);
+ for(i = 0; !result && (i < sizeof(heads)/sizeof(heads[0])); i++) {
+ if(!Curl_checkheaders(data, STRCONST(heads[i].name))) {
+#ifdef USE_HYPER
+ char field[128];
+ msnprintf(field, sizeof(field), "%s %s", heads[i].name,
+ heads[i].val);
+ result = Curl_hyper_header(data, req, field);
+#else
+ (void)data;
+ result = Curl_dyn_addf(req, "%s %s\r\n", heads[i].name,
+ heads[i].val);
+#endif
+ }
+ }
+ k->upgr101 = UPGR101_WS;
+ Curl_dyn_init(&data->req.p.http->ws.buf, MAX_WS_SIZE * 2);
+ return result;
+}
+
+CURLcode Curl_ws_accept(struct Curl_easy *data)
+{
+ struct SingleRequest *k = &data->req;
+ struct HTTP *ws = data->req.p.http;
+ struct connectdata *conn = data->conn;
+ struct websocket *wsp = &data->req.p.http->ws;
+ CURLcode result;
+
+ /* Verify the Sec-WebSocket-Accept response.
+
+ The sent value is the base64 encoded version of a SHA-1 hash done on the
+ |Sec-WebSocket-Key| header field concatenated with
+ the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".
+ */
+
+ /* If the response includes a |Sec-WebSocket-Extensions| header field and
+ this header field indicates the use of an extension that was not present
+ in the client's handshake (the server has indicated an extension not
+ requested by the client), the client MUST Fail the WebSocket Connection.
+ */
+
+ /* If the response includes a |Sec-WebSocket-Protocol| header field
+ and this header field indicates the use of a subprotocol that was
+ not present in the client's handshake (the server has indicated a
+ subprotocol not requested by the client), the client MUST Fail
+ the WebSocket Connection. */
+
+ /* 4 bytes random */
+ result = Curl_rand(data, (unsigned char *)&ws->ws.mask, sizeof(ws->ws.mask));
+ if(result)
+ return result;
+
+ infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
+ ws->ws.mask[0], ws->ws.mask[1], ws->ws.mask[2], ws->ws.mask[3]);
+ k->upgr101 = UPGR101_RECEIVED;
+
+ if(data->set.connect_only)
+ /* switch off non-blocking sockets */
+ (void)curlx_nonblock(conn->sock[FIRSTSOCKET], FALSE);
+
+ wsp->oleft = 0;
+ return result;
+}
+
+#define WSBIT_FIN 0x80
+#define WSBIT_OPCODE_CONT 0
+#define WSBIT_OPCODE_TEXT (1)
+#define WSBIT_OPCODE_BIN (2)
+#define WSBIT_OPCODE_CLOSE (8)
+#define WSBIT_OPCODE_PING (9)
+#define WSBIT_OPCODE_PONG (0xa)
+#define WSBIT_OPCODE_MASK (0xf)
+
+#define WSBIT_MASK 0x80
+
+/* remove the spent bytes from the beginning of the buffer as that part has
+ now been delivered to the application */
+static void ws_decode_clear(struct Curl_easy *data)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ size_t spent = wsp->usedbuf;
+ size_t len = Curl_dyn_len(&wsp->buf);
+ size_t keep = len - spent;
+ DEBUGASSERT(len >= spent);
+ Curl_dyn_tail(&wsp->buf, keep);
+}
+
+/* ws_decode() decodes a binary frame into structured WebSocket data,
+
+ wpkt - the incoming raw data. If NULL, work on the already buffered data.
+ ilen - the size of the provided data, perhaps too little, perhaps too much
+ out - stored pointed to extracted data
+ olen - stored length of the extracted data
+ oleft - number of unread bytes pending to that belongs to this frame
+ more - if there is more data in there
+ flags - stored bitmask about the frame
+
+ Returns CURLE_AGAIN if there is only a partial frame in the buffer. Then it
+ stores the first part in the ->extra buffer to be used in the next call
+ when more data is provided.
+*/
+
+static CURLcode ws_decode(struct Curl_easy *data,
+ unsigned char *wpkt, size_t ilen,
+ unsigned char **out, size_t *olen,
+ curl_off_t *oleft,
+ bool *more,
+ unsigned int *flags)
+{
+ bool fin;
+ unsigned char opcode;
+ curl_off_t total;
+ size_t dataindex = 2;
+ curl_off_t plen; /* size of data in the buffer */
+ curl_off_t payloadsize;
+ struct websocket *wsp = &data->req.p.http->ws;
+ unsigned char *p;
+ CURLcode result;
+
+ *olen = 0;
+
+ /* add the incoming bytes, if any */
+ if(wpkt) {
+ result = Curl_dyn_addn(&wsp->buf, wpkt, ilen);
+ if(result)
+ return result;
+ }
+
+ plen = Curl_dyn_len(&wsp->buf);
+ if(plen < 2) {
+ /* the smallest possible frame is two bytes */
+ infof(data, "WS: plen == %u, EAGAIN", (int)plen);
+ return CURLE_AGAIN;
+ }
+
+ p = Curl_dyn_uptr(&wsp->buf);
+
+ fin = p[0] & WSBIT_FIN;
+ opcode = p[0] & WSBIT_OPCODE_MASK;
+ infof(data, "WS:%d received FIN bit %u", __LINE__, (int)fin);
+ *flags = 0;
+ switch(opcode) {
+ case WSBIT_OPCODE_CONT:
+ if(!fin)
+ *flags |= CURLWS_CONT;
+ infof(data, "WS: received OPCODE CONT");
+ break;
+ case WSBIT_OPCODE_TEXT:
+ infof(data, "WS: received OPCODE TEXT");
+ *flags |= CURLWS_TEXT;
+ break;
+ case WSBIT_OPCODE_BIN:
+ infof(data, "WS: received OPCODE BINARY");
+ *flags |= CURLWS_BINARY;
+ break;
+ case WSBIT_OPCODE_CLOSE:
+ infof(data, "WS: received OPCODE CLOSE");
+ *flags |= CURLWS_CLOSE;
+ break;
+ case WSBIT_OPCODE_PING:
+ infof(data, "WS: received OPCODE PING");
+ *flags |= CURLWS_PING;
+ break;
+ case WSBIT_OPCODE_PONG:
+ infof(data, "WS: received OPCODE PONG");
+ *flags |= CURLWS_PONG;
+ break;
+ }
+
+ if(p[1] & WSBIT_MASK) {
+ /* A client MUST close a connection if it detects a masked frame. */
+ failf(data, "WS: masked input frame");
+ return CURLE_RECV_ERROR;
+ }
+ payloadsize = p[1];
+ if(payloadsize == 126) {
+ if(plen < 4) {
+ infof(data, "WS:%d plen == %u, EAGAIN", __LINE__, (int)plen);
+ return CURLE_AGAIN; /* not enough data available */
+ }
+ payloadsize = (p[2] << 8) | p[3];
+ dataindex += 2;
+ }
+ else if(payloadsize == 127) {
+ /* 64 bit payload size */
+ if(plen < 10)
+ return CURLE_AGAIN;
+ if(p[2] & 80) {
+ failf(data, "WS: too large frame");
+ return CURLE_RECV_ERROR;
+ }
+ dataindex += 8;
+ payloadsize = ((curl_off_t)p[2] << 56) |
+ (curl_off_t)p[3] << 48 |
+ (curl_off_t)p[4] << 40 |
+ (curl_off_t)p[5] << 32 |
+ (curl_off_t)p[6] << 24 |
+ (curl_off_t)p[7] << 16 |
+ (curl_off_t)p[8] << 8 |
+ p[9];
+ }
+
+ total = dataindex + payloadsize;
+ if(total > plen) {
+ /* deliver a partial frame */
+ *oleft = total - dataindex;
+ payloadsize = total - dataindex;
+ }
+ else {
+ *oleft = 0;
+ if(plen > total)
+ /* there is another fragment after */
+ *more = TRUE;
+ }
+
+ /* point to the payload */
+ *out = &p[dataindex];
+
+ /* return the payload length */
+ *olen = payloadsize;
+
+ /* number of bytes "used" from the buffer */
+ wsp->usedbuf = dataindex + payloadsize;
+ infof(data, "WS: received %zu bytes payload (%zu left)",
+ payloadsize, *oleft);
+ return CURLE_OK;
+}
+
+/* Curl_ws_writecb() is the write callback for websocket traffic. The
+ websocket data is provided to this raw, in chunks. This function should
+ handle/decode the data and call the "real" underlying callback accordingly.
+*/
+size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
+ size_t nitems, void *userp)
+{
+ struct HTTP *ws = (struct HTTP *)userp;
+ struct Curl_easy *data = ws->ws.data;
+ void *writebody_ptr = data->set.out;
+ if(data->set.ws_raw_mode)
+ return data->set.fwrite_func(buffer, size, nitems, writebody_ptr);
+ else if(nitems) {
+ unsigned char *frame = NULL;
+ size_t flen = 0;
+ size_t wrote = 0;
+ CURLcode result;
+ bool more; /* there's is more to parse in the buffer */
+ curl_off_t oleft;
+
+ decode:
+ more = FALSE;
+ oleft = ws->ws.frame.bytesleft;
+ if(!oleft) {
+ unsigned int recvflags;
+ result = ws_decode(data, (unsigned char *)buffer, nitems,
+ &frame, &flen, &oleft, &more, &recvflags);
+ if(result == CURLE_AGAIN)
+ /* insufficient amount of data, keep it for later */
+ return nitems;
+ else if(result) {
+ infof(data, "WS: decode error %d", (int)result);
+ return nitems - 1;
+ }
+ /* Store details about the frame to be reachable with curl_ws_meta()
+ from within the write callback */
+ ws->ws.frame.age = 0;
+ ws->ws.frame.offset = 0;
+ ws->ws.frame.flags = recvflags;
+ ws->ws.frame.bytesleft = oleft;
+ }
+ else {
+ if(nitems > (size_t)ws->ws.frame.bytesleft) {
+ nitems = ws->ws.frame.bytesleft;
+ more = TRUE;
+ }
+ else
+ more = FALSE;
+ ws->ws.frame.offset += nitems;
+ ws->ws.frame.bytesleft -= nitems;
+ frame = (unsigned char *)buffer;
+ flen = nitems;
+ }
+ if((ws->ws.frame.flags & CURLWS_PING) && !oleft) {
+ /* auto-respond to PINGs, only works for single-frame payloads atm */
+ size_t bytes;
+ infof(data, "WS: auto-respond to PING with a PONG");
+ DEBUGASSERT(frame);
+ /* send back the exact same content as a PONG */
+ result = curl_ws_send(data, frame, flen, &bytes, 0, CURLWS_PONG);
+ if(result)
+ return result;
+ }
+ else {
+ /* deliver the decoded frame to the user callback */
+ Curl_set_in_callback(data, true);
+ wrote = data->set.fwrite_func((char *)frame, 1, flen, writebody_ptr);
+ Curl_set_in_callback(data, false);
+ if(wrote != flen)
+ return 0;
+ }
+ if(oleft)
+ ws->ws.frame.offset += flen;
+ /* the websocket frame has been delivered */
+ ws_decode_clear(data);
+ if(more) {
+ /* there's more websocket data to deal with in the buffer */
+ buffer = NULL; /* the buffer as been drained already */
+ goto decode;
+ }
+ }
+ return nitems;
+}
+
+
+CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
+ size_t buflen, size_t *nread,
+ struct curl_ws_frame **metap)
+{
+ size_t bytes;
+ CURLcode result;
+ struct websocket *wsp = &data->req.p.http->ws;
+
+ *nread = 0;
+ *metap = NULL;
+ /* get a download buffer */
+ result = Curl_preconnect(data);
+ if(result)
+ return result;
+
+ do {
+ bool drain = FALSE; /* if there is pending buffered data to drain */
+ char *inbuf = data->state.buffer;
+ bytes = wsp->stillbuffer;
+ if(!bytes) {
+ result = curl_easy_recv(data, data->state.buffer,
+ data->set.buffer_size, &bytes);
+ if(result)
+ return result;
+ }
+ else {
+ /* the pending bytes can be found here */
+ inbuf = wsp->stillb;
+ drain = TRUE;
+ }
+ if(bytes) {
+ unsigned char *out;
+ size_t olen;
+ bool more;
+ unsigned int recvflags;
+ curl_off_t oleft = wsp->frame.bytesleft;
+
+ infof(data, "WS: got %u websocket bytes to decode", (int)bytes);
+ if(!oleft && !drain) {
+ result = ws_decode(data, (unsigned char *)inbuf, bytes,
+ &out, &olen, &oleft, &more, &recvflags);
+ if(result == CURLE_AGAIN)
+ /* a packet fragment only */
+ break;
+ else if(result)
+ return result;
+ wsp->frame.offset = 0;
+ wsp->frame.bytesleft = oleft;
+ wsp->frame.flags = recvflags;
+ }
+ else {
+ olen = oleft;
+ out = (unsigned char *)wsp->stillb;
+ recvflags = wsp->frame.flags;
+ if((curl_off_t)buflen < oleft)
+ /* there is still data left after this */
+ wsp->frame.bytesleft -= buflen;
+ else
+ wsp->frame.bytesleft = 0;
+ }
+
+ /* auto-respond to PINGs */
+ if((recvflags & CURLWS_PING) && !oleft) {
+ infof(data, "WS: auto-respond to PING with a PONG");
+ /* send back the exact same content as a PONG */
+ result = curl_ws_send(data, out, olen, &bytes, 0, CURLWS_PONG);
+ if(result)
+ return result;
+ }
+ else {
+ if(olen < buflen) {
+ /* copy the payload to the user buffer */
+ memcpy(buffer, out, olen);
+ *nread = olen;
+ if(!oleft)
+ /* websocket frame has been delivered */
+ ws_decode_clear(data);
+ }
+ else {
+ /* copy a partial payload */
+ memcpy(buffer, out, buflen);
+ *nread = buflen;
+ /* remember what is left and where */
+ wsp->stillbuffer = olen - buflen;
+ wsp->stillb = (char *)buffer + buflen;
+ }
+ wsp->frame.offset += *nread;
+ }
+ }
+ else
+ *nread = bytes;
+ break;
+ } while(1);
+ *metap = &wsp->frame;
+ return CURLE_OK;
+}
+
+static void ws_xor(struct Curl_easy *data,
+ const unsigned char *source,
+ unsigned char *dest,
+ size_t len)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ size_t i;
+ /* append payload after the mask, XOR appropriately */
+ for(i = 0; i < len; i++) {
+ dest[i] = source[i] ^ wsp->mask[wsp->xori];
+ wsp->xori++;
+ wsp->xori &= 3;
+ }
+}
+
+/***
+ RFC 6455 Section 5.2
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-------+-+-------------+-------------------------------+
+ |F|R|R|R| opcode|M| Payload len | Extended payload length |
+ |I|S|S|S| (4) |A| (7) | (16/64) |
+ |N|V|V|V| |S| | (if payload len==126/127) |
+ | |1|2|3| |K| | |
+ +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ | Extended payload length continued, if payload len == 127 |
+ + - - - - - - - - - - - - - - - +-------------------------------+
+ | |Masking-key, if MASK set to 1 |
+ +-------------------------------+-------------------------------+
+ | Masking-key (continued) | Payload Data |
+ +-------------------------------- - - - - - - - - - - - - - - - +
+ : Payload Data continued ... :
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ | Payload Data continued ... |
+ +---------------------------------------------------------------+
+*/
+
+static size_t ws_packethead(struct Curl_easy *data,
+ size_t len, unsigned int flags)
+{
+ struct HTTP *ws = data->req.p.http;
+ unsigned char *out = (unsigned char *)data->state.ulbuf;
+ unsigned char firstbyte = 0;
+ int outi;
+ unsigned char opcode;
+ if(flags & CURLWS_TEXT) {
+ opcode = WSBIT_OPCODE_TEXT;
+ infof(data, "WS: send OPCODE TEXT");
+ }
+ else if(flags & CURLWS_CLOSE) {
+ opcode = WSBIT_OPCODE_CLOSE;
+ infof(data, "WS: send OPCODE CLOSE");
+ }
+ else if(flags & CURLWS_PING) {
+ opcode = WSBIT_OPCODE_PING;
+ infof(data, "WS: send OPCODE PING");
+ }
+ else if(flags & CURLWS_PONG) {
+ opcode = WSBIT_OPCODE_PONG;
+ infof(data, "WS: send OPCODE PONG");
+ }
+ else {
+ opcode = WSBIT_OPCODE_BIN;
+ infof(data, "WS: send OPCODE BINARY");
+ }
+
+ if(!(flags & CURLWS_CONT)) {
+ /* if not marked as continuing, assume this is the final fragment */
+ firstbyte |= WSBIT_FIN | opcode;
+ ws->ws.contfragment = FALSE;
+ }
+ else if(ws->ws.contfragment) {
+ /* the previous fragment was not a final one and this isn't either, keep a
+ CONT opcode and no FIN bit */
+ firstbyte |= WSBIT_OPCODE_CONT;
+ }
+ else {
+ ws->ws.contfragment = TRUE;
+ }
+ out[0] = firstbyte;
+ if(len > 65535) {
+ out[1] = 127 | WSBIT_MASK;
+ out[2] = (len >> 8) & 0xff;
+ out[3] = len & 0xff;
+ outi = 10;
+ }
+ else if(len > 126) {
+ out[1] = 126 | WSBIT_MASK;
+ out[2] = (len >> 8) & 0xff;
+ out[3] = len & 0xff;
+ outi = 4;
+ }
+ else {
+ out[1] = (unsigned char)len | WSBIT_MASK;
+ outi = 2;
+ }
+
+ infof(data, "WS: send FIN bit %u (byte %02x)",
+ firstbyte & WSBIT_FIN ? 1 : 0,
+ firstbyte);
+ infof(data, "WS: send payload len %u", (int)len);
+
+ /* 4 bytes mask */
+ memcpy(&out[outi], &ws->ws.mask, 4);
+
+ if(data->set.upload_buffer_size < (len + 10))
+ return 0;
+
+ /* pass over the mask */
+ outi += 4;
+
+ ws->ws.xori = 0;
+ /* return packet size */
+ return outi;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t totalsize,
+ unsigned int sendflags)
+{
+ CURLcode result;
+ size_t headlen;
+ char *out;
+ ssize_t written;
+ struct websocket *wsp = &data->req.p.http->ws;
+
+ if(!data->set.ws_raw_mode) {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ }
+ else {
+ if(totalsize || sendflags)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ if(data->set.ws_raw_mode) {
+ if(!buflen)
+ /* nothing to do */
+ return CURLE_OK;
+ /* raw mode sends exactly what was requested, and this is from within
+ the write callback */
+ if(Curl_is_in_callback(data))
+ result = Curl_write(data, data->conn->writesockfd, buffer, buflen,
+ &written);
+ else
+ result = Curl_senddata(data, buffer, buflen, &written);
+
+ infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
+ buflen, written);
+ *sent = written;
+ return result;
+ }
+
+ if(buflen > (data->set.upload_buffer_size - 10))
+ /* don't do more than this in one go */
+ buflen = data->set.upload_buffer_size - 10;
+
+ if(sendflags & CURLWS_OFFSET) {
+ if(totalsize) {
+ /* a frame series 'totalsize' bytes big, this is the first */
+ headlen = ws_packethead(data, totalsize, sendflags);
+ wsp->sleft = totalsize - buflen;
+ }
+ else {
+ headlen = 0;
+ if((curl_off_t)buflen > wsp->sleft) {
+ infof(data, "WS: unaligned frame size (sending %zu instead of %zu)",
+ buflen, wsp->sleft);
+ wsp->sleft = 0;
+ }
+ else
+ wsp->sleft -= buflen;
+ }
+ }
+ else
+ headlen = ws_packethead(data, buflen, sendflags);
+
+ /* headlen is the size of the frame header */
+ out = data->state.ulbuf;
+ if(buflen)
+ /* for PING and PONG etc there might not be a payload */
+ ws_xor(data, buffer, (unsigned char *)out + headlen, buflen);
+
+ if(data->set.connect_only)
+ result = Curl_senddata(data, out, buflen + headlen, &written);
+ else
+ result = Curl_write(data, data->conn->writesockfd, out,
+ buflen + headlen, &written);
+
+ infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
+ headlen + buflen, written);
+ *sent = written;
+
+ return result;
+}
+
+void Curl_ws_done(struct Curl_easy *data)
+{
+ struct websocket *wsp = &data->req.p.http->ws;
+ DEBUGASSERT(wsp);
+ Curl_dyn_free(&wsp->buf);
+}
+
+CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ /* we only return something for websocket, called from within the callback
+ when not using raw mode */
+ if(GOOD_EASY_HANDLE(data) && Curl_is_in_callback(data) && data->req.p.http &&
+ !data->set.ws_raw_mode)
+ return &data->req.p.http->ws.frame;
+ return NULL;
+}
+
+#else
+
+CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *nread,
+ struct curl_ws_frame **metap)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)nread;
+ (void)metap;
+ return CURLE_OK;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t framesize,
+ unsigned int sendflags)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)sent;
+ (void)framesize;
+ (void)sendflags;
+ return CURLE_OK;
+}
+
+CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ (void)data;
+ return NULL;
+}
+#endif /* USE_WEBSOCKETS */
diff --git a/Utilities/cmcurl/lib/ws.h b/Utilities/cmcurl/lib/ws.h
new file mode 100644
index 000000000..341242e50
--- /dev/null
+++ b/Utilities/cmcurl/lib/ws.h
@@ -0,0 +1,69 @@
+#ifndef HEADER_CURL_WS_H
+#define HEADER_CURL_WS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_WEBSOCKETS
+
+#ifdef USE_HYPER
+#define REQTYPE void
+#else
+#define REQTYPE struct dynbuf
+#endif
+
+/* this is the largest single fragment size we support */
+#define MAX_WS_SIZE 65535
+
+/* part of 'struct HTTP', when used in the 'struct SingleRequest' in the
+ Curl_easy struct */
+struct websocket {
+ bool contfragment; /* set TRUE if the previous fragment sent was not final */
+ unsigned char mask[4]; /* 32 bit mask for this connection */
+ struct Curl_easy *data; /* used for write callback handling */
+ struct dynbuf buf;
+ size_t usedbuf; /* number of leading bytes in 'buf' the most recent complete
+ websocket frame uses */
+ struct curl_ws_frame frame; /* the struct used for frame state */
+ curl_off_t oleft; /* outstanding number of payload bytes left from the
+ server */
+ curl_off_t stillbuffer; /* number of bytes left in the buffer to deliver in
+ the next curl_ws_recv() call */
+ char *stillb; /* the stillbuffer pending bytes are here */
+ curl_off_t sleft; /* outstanding number of payload bytes left to send */
+ unsigned int xori; /* xor index */
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
+CURLcode Curl_ws_accept(struct Curl_easy *data);
+
+size_t Curl_ws_writecb(char *buffer, size_t size, size_t nitems, void *userp);
+void Curl_ws_done(struct Curl_easy *data);
+
+#else
+#define Curl_ws_request(x,y) CURLE_OK
+#define Curl_ws_done(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_WS_H */
diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt
index 9a62b79af..81dfee312 100644
--- a/Utilities/cmexpat/CMakeLists.txt
+++ b/Utilities/cmexpat/CMakeLists.txt
@@ -6,6 +6,12 @@ ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
ENDIF()
+# Activate POSIX APIs.
+if(CMAKE_SYSTEM_NAME MATCHES "^(Linux)$")
+ add_definitions(-D_DEFAULT_SOURCE -D_BSD_SOURCE)
+ string(APPEND CMAKE_REQUIRED_DEFINITIONS " -D_DEFAULT_SOURCE -D_BSD_SOURCE")
+endif()
+
include(ConfigureChecks.cmake)
configure_file(expat_config.h.cmake expat_config.h @ONLY)
diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index c384f4e1e..09579d2c3 100644
--- a/Utilities/cmjsoncpp/CMakeLists.txt
+++ b/Utilities/cmjsoncpp/CMakeLists.txt
@@ -21,5 +21,5 @@ include_directories(
)
add_library(cmjsoncpp ${JSONCPP_SOURCES})
-target_link_libraries(cmjsoncpp ${CMake_KWIML_LIBRARIES})
+target_link_libraries(cmjsoncpp $<TARGET_NAME_IF_EXISTS:kwiml::kwiml>)
set_property(TARGET cmjsoncpp PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index eea472f4c..b38e6530a 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -442,6 +442,8 @@ SET(ADDITIONAL_LIBS "")
#
IF(ENABLE_ZLIB)
FIND_PACKAGE(ZLIB)
+ SET(ZLIB_INCLUDE_DIR "")
+ SET(ZLIB_LIBRARIES ZLIB::ZLIB)
ELSE()
SET(ZLIB_FOUND FALSE) # Override cached value
ENDIF()
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index b815a5cf2..ad3d43382 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -27,6 +27,8 @@ set(uv_sources
src/queue.h
src/strscpy.c
src/strscpy.h
+ src/strtok.c
+ src/strtok.h
src/threadpool.c
src/timer.c
src/uv-common.c
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index 747095f1f..ffe34ecb1 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -1150,8 +1150,8 @@ struct uv_interface_address_s {
struct uv_passwd_s {
char* username;
- long uid;
- long gid;
+ unsigned long uid;
+ unsigned long gid;
char* shell;
char* homedir;
};
@@ -1259,6 +1259,7 @@ UV_EXTERN uv_pid_t uv_os_getppid(void);
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
+UV_EXTERN unsigned int uv_available_parallelism(void);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
UV_EXTERN int uv_cpumask_size(void);
diff --git a/Utilities/cmlibuv/include/uv/version.h b/Utilities/cmlibuv/include/uv/version.h
index 1934f390d..9c9d292f6 100644
--- a/Utilities/cmlibuv/include/uv/version.h
+++ b/Utilities/cmlibuv/include/uv/version.h
@@ -31,10 +31,10 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 43
-#define UV_VERSION_PATCH 1
-#define UV_VERSION_IS_RELEASE 0
-#define UV_VERSION_SUFFIX "dev"
+#define UV_VERSION_MINOR 44
+#define UV_VERSION_PATCH 2
+#define UV_VERSION_IS_RELEASE 1
+#define UV_VERSION_SUFFIX ""
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
(UV_VERSION_MINOR << 8) | \
diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h
index e3fe37d50..2662b0a28 100644
--- a/Utilities/cmlibuv/include/uv/win.h
+++ b/Utilities/cmlibuv/include/uv/win.h
@@ -234,7 +234,7 @@ typedef struct _AFD_POLL_INFO {
AFD_POLL_HANDLE_INFO Handles[1];
} AFD_POLL_INFO, *PAFD_POLL_INFO;
-#define UV_MSAFD_PROVIDER_COUNT 3
+#define UV_MSAFD_PROVIDER_COUNT 4
/**
@@ -388,6 +388,12 @@ typedef struct {
OVERLAPPED overlapped; \
size_t queued_bytes; \
} io; \
+ /* in v2, we can move these to the UV_CONNECT_PRIVATE_FIELDS */ \
+ struct { \
+ ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\
+ HANDLE pipeHandle; \
+ DWORD duplex_flags; \
+ } connect; \
} u; \
struct uv_req_s* next_req;
diff --git a/Utilities/cmlibuv/src/fs-poll.c b/Utilities/cmlibuv/src/fs-poll.c
index 89864e23f..1bac1c568 100644
--- a/Utilities/cmlibuv/src/fs-poll.c
+++ b/Utilities/cmlibuv/src/fs-poll.c
@@ -25,7 +25,7 @@
#ifdef _WIN32
#include "win/internal.h"
#include "win/handle-inl.h"
-#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
+#define uv__make_close_pending(h) uv__want_endgame((h)->loop, (h))
#else
#include "unix/internal.h"
#endif
diff --git a/Utilities/cmlibuv/src/idna.c b/Utilities/cmlibuv/src/idna.c
index b44cb16a1..93d982ca0 100644
--- a/Utilities/cmlibuv/src/idna.c
+++ b/Utilities/cmlibuv/src/idna.c
@@ -21,6 +21,7 @@
#include "idna.h"
#include <assert.h>
#include <string.h>
+#include <limits.h> /* UINT_MAX */
static unsigned uv__utf8_decode1_slow(const char** p,
const char* pe,
@@ -129,7 +130,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
while (s < se) {
c = uv__utf8_decode1(&s, se);
- if (c == -1u)
+ if (c == UINT_MAX)
return UV_EINVAL;
if (c < 128)
@@ -151,7 +152,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
s = ss;
while (s < se) {
c = uv__utf8_decode1(&s, se);
- assert(c != -1u);
+ assert(c != UINT_MAX);
if (c > 127)
continue;
@@ -182,7 +183,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
while (s < se) {
c = uv__utf8_decode1(&s, se);
- assert(c != -1u);
+ assert(c != UINT_MAX);
if (c >= n)
if (c < m)
@@ -201,7 +202,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
s = ss;
while (s < se) {
c = uv__utf8_decode1(&s, se);
- assert(c != -1u);
+ assert(c != UINT_MAX);
if (c < n)
if (++delta == 0)
@@ -280,7 +281,7 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
st = si;
c = uv__utf8_decode1(&si, se);
- if (c == -1u)
+ if (c == UINT_MAX)
return UV_EINVAL;
if (c != '.')
diff --git a/Utilities/cmlibuv/src/strscpy.h b/Utilities/cmlibuv/src/strscpy.h
index cc78149db..e8d47247f 100644
--- a/Utilities/cmlibuv/src/strscpy.h
+++ b/Utilities/cmlibuv/src/strscpy.h
@@ -28,7 +28,7 @@
*/
#include "uv.h"
-/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates
+/* Copies up to |n-1| bytes from |s| to |d| and always zero-terminates
* the result, except when |n==0|. Returns the number of bytes copied
* or UV_E2BIG if |d| is too small.
*
diff --git a/Utilities/cmlibuv/src/strtok.c b/Utilities/cmlibuv/src/strtok.c
new file mode 100644
index 000000000..45ddea50b
--- /dev/null
+++ b/Utilities/cmlibuv/src/strtok.c
@@ -0,0 +1,52 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include "strtok.h"
+
+char* uv__strtok(char* str, const char* sep, char** itr) {
+ const char* sep_itr;
+ char* tmp;
+ char* start;
+
+ if (str == NULL)
+ start = tmp = *itr;
+ else
+ start = tmp = str;
+
+ if (tmp == NULL)
+ return NULL;
+
+ while (*tmp != '\0') {
+ sep_itr = sep;
+ while (*sep_itr != '\0') {
+ if (*tmp == *sep_itr) {
+ *itr = tmp + 1;
+ *tmp = '\0';
+ return start;
+ }
+ sep_itr++;
+ }
+ tmp++;
+ }
+ *itr = NULL;
+ return start;
+}
diff --git a/Utilities/cmlibuv/src/strtok.h b/Utilities/cmlibuv/src/strtok.h
new file mode 100644
index 000000000..3799ff554
--- /dev/null
+++ b/Utilities/cmlibuv/src/strtok.h
@@ -0,0 +1,27 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UV_STRTOK_H_
+#define UV_STRTOK_H_
+
+char* uv__strtok(char* str, const char* sep, char** itr);
+
+#endif /* UV_STRTOK_H_ */
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index 63d8268ab..2b5816215 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -43,12 +43,11 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
__compare_and_swap((volatile int*)ptr, &oldval, newval);
return oldval;
#elif defined(__MVS__)
- unsigned int op4;
- if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
- (unsigned int*) ptr, *ptr, &op4))
- return oldval;
- else
- return op4;
+ /* Use hand-rolled assembly because codegen from builtin __plo_CSST results in
+ * a runtime bug.
+ */
+ __asm(" cs %0,%2,%1 \n " : "+r"(oldval), "+m"(*ptr) : "r"(newval) :);
+ return oldval;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
#else
@@ -61,7 +60,9 @@ UV_UNUSED(static void cpu_relax(void)) {
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
__asm__ __volatile__ ("yield" ::: "memory");
-#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
+#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__)
+ __asm volatile ("" : : : "memory");
+#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
#endif
}
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index e48934bce..11ca95591 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -27,7 +27,7 @@
#include <ifaddrs.h>
#include <net/if.h>
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
#include <net/if_dl.h>
#endif
@@ -40,7 +40,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return 1;
if (ent->ifa_addr == NULL)
return 1;
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
/*
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`
* equals `AF_LINK`. Otherwise, the result depends on the operating
@@ -69,7 +69,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs* addrs;
struct ifaddrs* ent;
uv_interface_address_t* address;
-#if !(defined(__CYGWIN__) || defined(__MSYS__))
+#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
int i;
#endif
@@ -126,7 +126,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address++;
}
-#if !(defined(__CYGWIN__) || defined(__MSYS__))
+#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
diff --git a/Utilities/cmlibuv/src/unix/bsd-proctitle.c b/Utilities/cmlibuv/src/unix/bsd-proctitle.c
index 4f4e9e518..b0c01e2cb 100644
--- a/Utilities/cmlibuv/src/unix/bsd-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/bsd-proctitle.c
@@ -38,6 +38,7 @@ static void init_process_title_mutex_once(void) {
void uv__process_title_cleanup(void) {
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_destroy(&process_title_mutex);
}
diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
index 0f279d521..394231d1b 100644
--- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
+++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
@@ -135,7 +135,9 @@ int uv__statx(int dirfd,
errno = ENOSYS;
return -1;
}
+#endif
+#if defined(__linux__) || defined(__FreeBSD__)
ssize_t uv__fs_copy_file_range(int fd_in, off_t* off_in,
int fd_out, off_t* off_out,
size_t len, unsigned int flags)
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index 079392247..d0b0e0069 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -20,6 +20,7 @@
#include "uv.h"
#include "internal.h"
+#include "strtok.h"
#include <stddef.h> /* NULL */
#include <stdio.h> /* printf */
@@ -86,10 +87,12 @@ extern char** environ;
#endif
#if defined(__MVS__)
-#include <sys/ioctl.h>
+# include <sys/ioctl.h>
+# include "zos-sys-info.h"
#endif
#if defined(__linux__)
+# include <sched.h>
# include <sys/syscall.h>
# define uv__accept4 accept4
#endif
@@ -98,7 +101,7 @@ extern char** environ;
# include <sanitizer/linux_syscall_hooks.h>
#endif
-static int uv__run_pending(uv_loop_t* loop);
+static void uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
@@ -164,6 +167,15 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_FS_EVENT:
uv__fs_event_close((uv_fs_event_t*)handle);
+#if defined(__sun) || defined(__MVS__)
+ /*
+ * On Solaris, illumos, and z/OS we will not be able to dissociate the
+ * watcher for an event which is pending delivery, so we cannot always call
+ * uv__make_close_pending() straight away. The backend will call the
+ * function once the event has cleared.
+ */
+ return;
+#endif
break;
case UV_POLL:
@@ -340,42 +352,43 @@ int uv_backend_fd(const uv_loop_t* loop) {
}
-int uv_backend_timeout(const uv_loop_t* loop) {
- if (loop->stop_flag != 0)
- return 0;
-
- if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
- return 0;
-
- if (!QUEUE_EMPTY(&loop->idle_handles))
- return 0;
-
- if (!QUEUE_EMPTY(&loop->pending_queue))
- return 0;
+static int uv__loop_alive(const uv_loop_t* loop) {
+ return uv__has_active_handles(loop) ||
+ uv__has_active_reqs(loop) ||
+ !QUEUE_EMPTY(&loop->pending_queue) ||
+ loop->closing_handles != NULL;
+}
- if (loop->closing_handles)
- return 0;
- return uv__next_timeout(loop);
+static int uv__backend_timeout(const uv_loop_t* loop) {
+ if (loop->stop_flag == 0 &&
+ /* uv__loop_alive(loop) && */
+ (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
+ QUEUE_EMPTY(&loop->pending_queue) &&
+ QUEUE_EMPTY(&loop->idle_handles) &&
+ loop->closing_handles == NULL)
+ return uv__next_timeout(loop);
+ return 0;
}
-static int uv__loop_alive(const uv_loop_t* loop) {
- return uv__has_active_handles(loop) ||
- uv__has_active_reqs(loop) ||
- loop->closing_handles != NULL;
+int uv_backend_timeout(const uv_loop_t* loop) {
+ if (QUEUE_EMPTY(&loop->watcher_queue))
+ return uv__backend_timeout(loop);
+ /* Need to call uv_run to update the backend fd state. */
+ return 0;
}
int uv_loop_alive(const uv_loop_t* loop) {
- return uv__loop_alive(loop);
+ return uv__loop_alive(loop);
}
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
int timeout;
int r;
- int ran_pending;
+ int can_sleep;
r = uv__loop_alive(loop);
if (!r)
@@ -384,16 +397,25 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
- ran_pending = uv__run_pending(loop);
+
+ can_sleep =
+ QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles);
+
+ uv__run_pending(loop);
uv__run_idle(loop);
uv__run_prepare(loop);
timeout = 0;
- if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
- timeout = uv_backend_timeout(loop);
+ if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
+ timeout = uv__backend_timeout(loop);
uv__io_poll(loop, timeout);
+ /* Process immediate callbacks (e.g. write_cb) a small fixed number of
+ * times to avoid loop starvation.*/
+ for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++)
+ uv__run_pending(loop);
+
/* Run one final update on the provider_idle_time in case uv__io_poll
* returned because the timeout expired, but no events were received. This
* call will be ignored if the provider_entry_time was either never set (if
@@ -603,20 +625,6 @@ int uv__nonblock_ioctl(int fd, int set) {
return 0;
}
-
-
-int uv__cloexec_ioctl(int fd, int set) {
- int r;
-
- do
- r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
- while (r == -1 && errno == EINTR);
-
- if (r)
- return UV__ERR(errno);
-
- return 0;
-}
#endif
@@ -651,25 +659,13 @@ int uv__nonblock_fcntl(int fd, int set) {
}
-int uv__cloexec_fcntl(int fd, int set) {
+int uv__cloexec(int fd, int set) {
int flags;
int r;
- do
- r = fcntl(fd, F_GETFD);
- while (r == -1 && errno == EINTR);
-
- if (r == -1)
- return UV__ERR(errno);
-
- /* Bail out now if already set/clear. */
- if (!!(r & FD_CLOEXEC) == !!set)
- return 0;
-
+ flags = 0;
if (set)
- flags = r | FD_CLOEXEC;
- else
- flags = r & ~FD_CLOEXEC;
+ flags = FD_CLOEXEC;
do
r = fcntl(fd, F_SETFD, flags);
@@ -683,28 +679,23 @@ int uv__cloexec_fcntl(int fd, int set) {
ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
- struct cmsghdr* cmsg;
+#if defined(__ANDROID__) || \
+ defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__NetBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__linux__)
ssize_t rc;
+ rc = recvmsg(fd, msg, flags | MSG_CMSG_CLOEXEC);
+ if (rc == -1)
+ return UV__ERR(errno);
+ return rc;
+#else
+ struct cmsghdr* cmsg;
int* pfd;
int* end;
-#if defined(__linux__)
- static int no_msg_cmsg_cloexec;
- if (0 == uv__load_relaxed(&no_msg_cmsg_cloexec)) {
- rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */
- if (rc != -1)
- return rc;
- if (errno != EINVAL)
- return UV__ERR(errno);
- rc = recvmsg(fd, msg, flags);
- if (rc == -1)
- return UV__ERR(errno);
- uv__store_relaxed(&no_msg_cmsg_cloexec, 1);
- } else {
- rc = recvmsg(fd, msg, flags);
- }
-#else
+ ssize_t rc;
rc = recvmsg(fd, msg, flags);
-#endif
if (rc == -1)
return UV__ERR(errno);
if (msg->msg_controllen == 0)
@@ -717,6 +708,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
pfd += 1)
uv__cloexec(*pfd, 1);
return rc;
+#endif
}
@@ -809,14 +801,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
}
-static int uv__run_pending(uv_loop_t* loop) {
+static void uv__run_pending(uv_loop_t* loop) {
QUEUE* q;
QUEUE pq;
uv__io_t* w;
- if (QUEUE_EMPTY(&loop->pending_queue))
- return 0;
-
QUEUE_MOVE(&loop->pending_queue, &pq);
while (!QUEUE_EMPTY(&pq)) {
@@ -826,8 +815,6 @@ static int uv__run_pending(uv_loop_t* loop) {
w = QUEUE_DATA(q, uv__io_t, pending_queue);
w->cb(loop, w, POLLOUT);
}
-
- return 1;
}
@@ -1042,6 +1029,32 @@ int uv__open_cloexec(const char* path, int flags) {
}
+int uv__slurp(const char* filename, char* buf, size_t len) {
+ ssize_t n;
+ int fd;
+
+ assert(len > 0);
+
+ fd = uv__open_cloexec(filename, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ do
+ n = read(fd, buf, len - 1);
+ while (n == -1 && errno == EINTR);
+
+ if (uv__close_nocheckstdio(fd))
+ abort();
+
+ if (n < 0)
+ return UV__ERR(errno);
+
+ buf[n] = '\0';
+
+ return 0;
+}
+
+
int uv__dup2_cloexec(int oldfd, int newfd) {
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__)
int r;
@@ -1166,24 +1179,17 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
size_t name_size;
size_t homedir_size;
size_t shell_size;
- long initsize;
int r;
if (pwd == NULL)
return UV_EINVAL;
- initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-
- if (initsize <= 0)
- bufsize = 4096;
- else
- bufsize = (size_t) initsize;
-
uid = geteuid();
- buf = NULL;
- for (;;) {
- uv__free(buf);
+ /* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it
+ * is frequently 1024 or 4096, so we can just use that directly. The pwent
+ * will not usually be large. */
+ for (bufsize = 2000;; bufsize *= 2) {
buf = uv__malloc(bufsize);
if (buf == NULL)
@@ -1193,21 +1199,18 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
while (r == EINTR);
+ if (r != 0 || result == NULL)
+ uv__free(buf);
+
if (r != ERANGE)
break;
-
- bufsize *= 2;
}
- if (r != 0) {
- uv__free(buf);
+ if (r != 0)
return UV__ERR(r);
- }
- if (result == NULL) {
- uv__free(buf);
+ if (result == NULL)
return UV_ENOENT;
- }
/* Allocate memory for the username, shell, and home directory */
name_size = strlen(pw.pw_name) + 1;
@@ -1569,6 +1572,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
char* cloned_path;
char* path_env;
char* token;
+ char* itr;
if (buf == NULL || buflen == NULL || *buflen == 0)
return UV_EINVAL;
@@ -1610,7 +1614,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
if (cloned_path == NULL)
return UV_ENOMEM;
- token = strtok(cloned_path, ":");
+ token = uv__strtok(cloned_path, ":", &itr);
while (token != NULL) {
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog);
if (realpath(trypath, abspath) == abspath) {
@@ -1629,10 +1633,50 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
return 0;
}
}
- token = strtok(NULL, ":");
+ token = uv__strtok(NULL, ":", &itr);
}
uv__free(cloned_path);
/* Out of tokens (path entries), and no match found */
return UV_EINVAL;
}
+
+
+unsigned int uv_available_parallelism(void) {
+#ifdef __linux__
+ cpu_set_t set;
+ long rc;
+
+ memset(&set, 0, sizeof(set));
+
+ /* sysconf(_SC_NPROCESSORS_ONLN) in musl calls sched_getaffinity() but in
+ * glibc it's... complicated... so for consistency try sched_getaffinity()
+ * before falling back to sysconf(_SC_NPROCESSORS_ONLN).
+ */
+ if (0 == sched_getaffinity(0, sizeof(set), &set))
+ rc = CPU_COUNT(&set);
+ else
+ rc = sysconf(_SC_NPROCESSORS_ONLN);
+
+ if (rc < 1)
+ rc = 1;
+
+ return (unsigned) rc;
+#elif defined(__MVS__)
+ int rc;
+
+ rc = __get_num_online_cpus();
+ if (rc < 1)
+ rc = 1;
+
+ return (unsigned) rc;
+#else /* __linux__ */
+ long rc;
+
+ rc = sysconf(_SC_NPROCESSORS_ONLN);
+ if (rc < 1)
+ rc = 1;
+
+ return (unsigned) rc;
+#endif /* __linux__ */
+}
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index 170b897e2..658ff262d 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -287,3 +287,18 @@ int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
return errno = ENOSYS, -1;
#endif
}
+
+ssize_t
+uv__fs_copy_file_range(int fd_in,
+ off_t* off_in,
+ int fd_out,
+ off_t* off_out,
+ size_t len,
+ unsigned int flags)
+{
+#if __FreeBSD__ >= 13 && !defined(__DragonFly__)
+ return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 40448f1c7..e2db3ad66 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -247,7 +247,8 @@ UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
static ssize_t uv__fs_futime(uv_fs_t* req) {
#if defined(__linux__) \
|| defined(_AIX71) \
- || defined(__HAIKU__)
+ || defined(__HAIKU__) \
+ || defined(__GNU__)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
@@ -1085,6 +1086,17 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
*/
#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__)
+ off_t off;
+
+ off = req->off;
+ r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0);
+ if (r >= 0) {
+ r = off - req->off;
+ req->off = off;
+ return r;
+ }
+#endif
len = 0;
r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
#elif defined(__FreeBSD_kernel__)
@@ -1179,7 +1191,9 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
#if defined(__linux__) || \
defined(_AIX71) || \
defined(__sun) || \
- defined(__HAIKU__)
+ defined(__HAIKU__) || \
+ defined(__GNU__) || \
+ defined(__OpenBSD__)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
diff --git a/Utilities/cmlibuv/src/unix/hurd.c b/Utilities/cmlibuv/src/unix/hurd.c
new file mode 100644
index 000000000..d19ea6347
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/hurd.c
@@ -0,0 +1,167 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#define _GNU_SOURCE 1
+
+#include "uv.h"
+#include "internal.h"
+
+#include <hurd.h>
+#include <hurd/process.h>
+#include <mach/task_info.h>
+#include <mach/vm_statistics.h>
+#include <mach/vm_param.h>
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+
+int uv_exepath(char* buffer, size_t* size) {
+ kern_return_t err;
+ /* XXX in current Hurd, strings are char arrays of 1024 elements */
+ string_t exepath;
+ ssize_t copied;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ if (*size - 1 > 0) {
+ /* XXX limited length of buffer in current Hurd, this API will probably
+ * evolve in the future */
+ err = proc_get_exe(getproc(), getpid(), exepath);
+
+ if (err)
+ return UV__ERR(err);
+ }
+
+ copied = uv__strscpy(buffer, exepath, *size);
+
+ /* do not return error on UV_E2BIG failure */
+ *size = copied < 0 ? strlen(buffer) : (size_t) copied;
+
+ return 0;
+}
+
+int uv_resident_set_memory(size_t* rss) {
+ kern_return_t err;
+ struct task_basic_info bi;
+ mach_msg_type_number_t count;
+
+ count = TASK_BASIC_INFO_COUNT;
+ err = task_info(mach_task_self(), TASK_BASIC_INFO,
+ (task_info_t) &bi, &count);
+
+ if (err)
+ return UV__ERR(err);
+
+ *rss = bi.resident_size;
+
+ return 0;
+}
+
+uint64_t uv_get_free_memory(void) {
+ kern_return_t err;
+ struct vm_statistics vmstats;
+
+ err = vm_statistics(mach_task_self(), &vmstats);
+
+ if (err)
+ return 0;
+
+ return vmstats.free_count * vm_page_size;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+ kern_return_t err;
+ host_basic_info_data_t hbi;
+ mach_msg_type_number_t cnt;
+
+ cnt = HOST_BASIC_INFO_COUNT;
+ err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt);
+
+ if (err)
+ return 0;
+
+ return hbi.memory_size;
+}
+
+
+int uv_uptime(double* uptime) {
+ char buf[128];
+
+ /* Try /proc/uptime first */
+ if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf)))
+ if (1 == sscanf(buf, "%lf", uptime))
+ return 0;
+
+ /* Reimplement here code from procfs to calculate uptime if not mounted? */
+
+ return UV__ERR(EIO);
+}
+
+void uv_loadavg(double avg[3]) {
+ char buf[128]; /* Large enough to hold all of /proc/loadavg. */
+
+ if (0 == uv__slurp("/proc/loadavg", buf, sizeof(buf)))
+ if (3 == sscanf(buf, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]))
+ return;
+
+ /* Reimplement here code from procfs to calculate loadavg if not mounted? */
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+ kern_return_t err;
+ host_basic_info_data_t hbi;
+ mach_msg_type_number_t cnt;
+
+ /* Get count of cpus */
+ cnt = HOST_BASIC_INFO_COUNT;
+ err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt);
+
+ if (err) {
+ err = UV__ERR(err);
+ goto abort;
+ }
+
+ /* XXX not implemented on the Hurd */
+ *cpu_infos = uv__calloc(hbi.avail_cpus, sizeof(**cpu_infos));
+ if (*cpu_infos == NULL) {
+ err = UV_ENOMEM;
+ goto abort;
+ }
+
+ *count = hbi.avail_cpus;
+
+ return 0;
+
+ abort:
+ *cpu_infos = NULL;
+ *count = 0;
+ return err;
+}
+
+uint64_t uv_get_constrained_memory(void) {
+ return 0; /* Memory constraints are unknown. */
+}
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 586ae390d..f41ee3cd9 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -155,7 +155,8 @@ typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
/* loop flags */
enum {
- UV_LOOP_BLOCK_SIGPROF = 1
+ UV_LOOP_BLOCK_SIGPROF = 0x1,
+ UV_LOOP_REAP_CHILDREN = 0x2
};
/* flags of excluding ifaddr */
@@ -184,11 +185,9 @@ struct uv__stream_queued_fds_s {
defined(__linux__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
-#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_ioctl
#define UV__NONBLOCK_IS_IOCTL 1
#else
-#define uv__cloexec uv__cloexec_fcntl
#define uv__nonblock uv__nonblock_fcntl
#define UV__NONBLOCK_IS_IOCTL 0
#endif
@@ -206,8 +205,7 @@ struct uv__stream_queued_fds_s {
#endif
/* core */
-int uv__cloexec_ioctl(int fd, int set);
-int uv__cloexec_fcntl(int fd, int set);
+int uv__cloexec(int fd, int set);
int uv__nonblock_ioctl(int fd, int set);
int uv__nonblock_fcntl(int fd, int set);
int uv__close(int fd); /* preserves errno */
@@ -251,14 +249,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
int uv__accept(int sockfd);
int uv__dup2_cloexec(int oldfd, int newfd);
int uv__open_cloexec(const char* path, int flags);
+int uv__slurp(const char* filename, char* buf, size_t len);
/* tcp */
-int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
+int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
int uv__tcp_nodelay(int fd, int on);
int uv__tcp_keepalive(int fd, int on, unsigned int delay);
/* pipe */
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
+int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
/* signal */
void uv__signal_close(uv_signal_t* handle);
@@ -288,10 +287,10 @@ void uv__tcp_close(uv_tcp_t* handle);
size_t uv__thread_stack_size(void);
void uv__udp_close(uv_udp_t* handle);
void uv__udp_finish_close(uv_udp_t* handle);
-uv_handle_type uv__handle_type(int fd);
FILE* uv__open_file(const char* path);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__search_path(const char* prog, char* buf, size_t* buflen);
+void uv__wait_children(uv_loop_t* loop);
/* random */
int uv__random_devurandom(void* buf, size_t buflen);
@@ -366,5 +365,15 @@ size_t strnlen(const char* s, size_t maxlen);
#endif
#endif
+#if defined(__FreeBSD__)
+ssize_t
+uv__fs_copy_file_range(int fd_in,
+ off_t* off_in,
+ int fd_out,
+ off_t* off_out,
+ size_t len,
+ unsigned int flags);
+#endif
+
#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index 75e911070..5dac76ae7 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -117,6 +117,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
unsigned int revents;
QUEUE* q;
uv__io_t* w;
+ uv_process_t* process;
sigset_t* pset;
sigset_t set;
uint64_t base;
@@ -285,6 +286,21 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
for (i = 0; i < nfds; i++) {
ev = events + i;
fd = ev->ident;
+
+ /* Handle kevent NOTE_EXIT results */
+ if (ev->filter == EVFILT_PROC) {
+ QUEUE_FOREACH(q, &loop->process_handles) {
+ process = QUEUE_DATA(q, uv_process_t, queue);
+ if (process->pid == fd) {
+ process->flags |= UV_HANDLE_REAP;
+ loop->flags |= UV_LOOP_REAP_CHILDREN;
+ break;
+ }
+ }
+ nevents++;
+ continue;
+ }
+
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;
@@ -377,6 +393,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
nevents++;
}
+ if (loop->flags & UV_LOOP_REAP_CHILDREN) {
+ loop->flags &= ~UV_LOOP_REAP_CHILDREN;
+ uv__wait_children(loop);
+ }
+
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
@@ -435,7 +456,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
- if ((int) events[i].ident == fd)
+ if ((int) events[i].ident == fd && events[i].filter != EVFILT_PROC)
events[i].ident = -1;
}
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 7b041e685..23a7dafec 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -211,31 +211,6 @@ err:
return UV_EINVAL;
}
-static int uv__slurp(const char* filename, char* buf, size_t len) {
- ssize_t n;
- int fd;
-
- assert(len > 0);
-
- fd = uv__open_cloexec(filename, O_RDONLY);
- if (fd < 0)
- return fd;
-
- do
- n = read(fd, buf, len - 1);
- while (n == -1 && errno == EINTR);
-
- if (uv__close_nocheckstdio(fd))
- abort();
-
- if (n < 0)
- return UV__ERR(errno);
-
- buf[n] = '\0';
-
- return 0;
-}
-
int uv_uptime(double* uptime) {
static volatile int no_clock_boottime;
char buf[128];
@@ -243,7 +218,7 @@ int uv_uptime(double* uptime) {
int r;
/* Try /proc/uptime first, then fallback to clock_gettime(). */
-
+
if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf)))
if (1 == sscanf(buf, "%lf", uptime))
return 0;
@@ -641,6 +616,7 @@ static uint64_t read_cpufreq(unsigned int cpunum) {
}
+#ifdef HAVE_IFADDRS_H
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
@@ -654,6 +630,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return exclude_type;
return !exclude_type;
}
+#endif
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#ifndef HAVE_IFADDRS_H
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
index a74112701..5861aaaa2 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -284,6 +284,8 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
nmsgsfds_t size;
struct pollfd* pfds;
int pollret;
+ int pollfdret;
+ int pollmsgret;
int reventcount;
int nevents;
struct pollfd msg_fd;
@@ -304,24 +306,24 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
return -1;
}
- if (lst->size > 0)
- _SET_FDS_MSGS(size, 1, lst->size - 1);
- else
- _SET_FDS_MSGS(size, 0, 0);
+ assert(lst->size > 0);
+ _SET_FDS_MSGS(size, 1, lst->size - 1);
pfds = lst->items;
pollret = poll(pfds, size, timeout);
if (pollret <= 0)
return pollret;
- assert(lst->size > 0);
-
- pollret = _NFDS(pollret) + _NMSGS(pollret);
+ pollfdret = _NFDS(pollret);
+ pollmsgret = _NMSGS(pollret);
reventcount = 0;
nevents = 0;
- msg_fd = pfds[lst->size - 1];
+ msg_fd = pfds[lst->size - 1]; /* message queue is always last entry */
+ maxevents = maxevents - pollmsgret; /* allow spot for message queue */
for (i = 0;
- i < lst->size && i < maxevents && reventcount < pollret; ++i) {
+ i < lst->size - 1 &&
+ nevents < maxevents &&
+ reventcount < pollfdret; ++i) {
struct epoll_event ev;
struct pollfd* pfd;
@@ -332,18 +334,18 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
ev.fd = pfd->fd;
ev.events = pfd->revents;
ev.is_msg = 0;
- if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
- reventcount += 2;
- else if (pfd->revents & (POLLIN | POLLOUT))
- ++reventcount;
- pfd->revents = 0;
+ reventcount++;
events[nevents++] = ev;
}
- if (msg_fd.revents != 0 && msg_fd.fd != -1)
- if (i == lst->size)
- events[nevents - 1].is_msg = 1;
+ if (pollmsgret > 0 && msg_fd.revents != 0 && msg_fd.fd != -1) {
+ struct epoll_event ev;
+ ev.fd = msg_fd.fd;
+ ev.events = msg_fd.revents;
+ ev.is_msg = 1;
+ events[nevents++] = ev;
+ }
return nevents;
}
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index bf0448b51..3b16318ce 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -278,7 +278,9 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
__net_ifconf6header_t ifc;
__net_ifconf6entry_t* ifr;
__net_ifconf6entry_t* p;
- __net_ifconf6entry_t flg;
+ unsigned int i;
+ int count_names;
+ unsigned char netmask[16] = {0};
*count = 0;
/* Assume maximum buffer size allowable */
@@ -287,24 +289,33 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
return UV__ERR(errno);
+ ifc.__nif6h_buffer = uv__calloc(1, maxsize);
+
+ if (ifc.__nif6h_buffer == NULL) {
+ uv__close(sockfd);
+ return UV_ENOMEM;
+ }
+
ifc.__nif6h_version = 1;
ifc.__nif6h_buflen = maxsize;
- ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
+ /* This will error on a system that does not support IPv6. However, we want
+ * to treat this as there being 0 interfaces so we can continue to get IPv4
+ * interfaces in uv_interface_addresses(). So return 0 instead of the error.
+ */
+ uv__free(ifc.__nif6h_buffer);
uv__close(sockfd);
- return UV__ERR(errno);
+ errno = 0;
+ return 0;
}
-
- *count = 0;
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
p = ifr;
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
- if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
- p->__nif6e_addr.sin6_family == AF_INET))
+ if (!(p->__nif6e_addr.sin6_family == AF_INET6))
continue;
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
@@ -313,21 +324,28 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
++(*count);
}
+ if ((*count) == 0) {
+ uv__free(ifc.__nif6h_buffer);
+ uv__close(sockfd);
+ return 0;
+ }
+
/* Alloc the return interface structs */
- *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
+ *addresses = uv__calloc(1, *count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
+ uv__free(ifc.__nif6h_buffer);
uv__close(sockfd);
return UV_ENOMEM;
}
address = *addresses;
+ count_names = 0;
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
p = ifr;
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
- if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
- p->__nif6e_addr.sin6_family == AF_INET))
+ if (!(p->__nif6e_addr.sin6_family == AF_INET6))
continue;
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
@@ -335,20 +353,41 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
/* All conditions above must match count loop */
- address->name = uv__strdup(p->__nif6e_name);
+ i = 0;
+ /* Ignore EBCDIC space (0x40) padding in name */
+ while (i < ARRAY_SIZE(p->__nif6e_name) &&
+ p->__nif6e_name[i] != 0x40 &&
+ p->__nif6e_name[i] != 0)
+ ++i;
+ address->name = uv__malloc(i + 1);
+ if (address->name == NULL) {
+ uv_free_interface_addresses(*addresses, count_names);
+ uv__free(ifc.__nif6h_buffer);
+ uv__close(sockfd);
+ return UV_ENOMEM;
+ }
+ memcpy(address->name, p->__nif6e_name, i);
+ address->name[i] = '\0';
+ __e2a_s(address->name);
+ count_names++;
- if (p->__nif6e_addr.sin6_family == AF_INET6)
- address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
- else
- address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
+ address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
- /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
+ for (i = 0; i < (p->__nif6e_prefixlen / 8); i++)
+ netmask[i] = 0xFF;
- address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
- memset(address->phys_addr, 0, sizeof(address->phys_addr));
+ if (p->__nif6e_prefixlen % 8)
+ netmask[i] = 0xFF << (8 - (p->__nif6e_prefixlen % 8));
+
+ address->netmask.netmask6.sin6_len = p->__nif6e_prefixlen;
+ memcpy(&(address->netmask.netmask6.sin6_addr), netmask, 16);
+ address->netmask.netmask6.sin6_family = AF_INET6;
+
+ address->is_internal = p->__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
address++;
}
+ uv__free(ifc.__nif6h_buffer);
uv__close(sockfd);
return 0;
}
@@ -362,14 +401,18 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifreq flg;
struct ifreq* ifr;
struct ifreq* p;
+ uv_interface_address_t* addresses_v6;
int count_v6;
+ unsigned int i;
+ int rc;
+ int count_names;
*count = 0;
*addresses = NULL;
/* get the ipv6 addresses first */
- uv_interface_address_t* addresses_v6;
- uv__interface_addresses_v6(&addresses_v6, &count_v6);
+ if ((rc = uv__interface_addresses_v6(&addresses_v6, &count_v6)) != 0)
+ return rc;
/* now get the ipv4 addresses */
@@ -377,12 +420,27 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
maxsize = 16384;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (0 > sockfd)
+ if (0 > sockfd) {
+ if (count_v6)
+ uv_free_interface_addresses(addresses_v6, count_v6);
return UV__ERR(errno);
+ }
ifc.ifc_req = uv__calloc(1, maxsize);
+
+ if (ifc.ifc_req == NULL) {
+ if (count_v6)
+ uv_free_interface_addresses(addresses_v6, count_v6);
+ uv__close(sockfd);
+ return UV_ENOMEM;
+ }
+
ifc.ifc_len = maxsize;
+
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
+ if (count_v6)
+ uv_free_interface_addresses(addresses_v6, count_v6);
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return UV__ERR(errno);
}
@@ -403,6 +461,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ if (count_v6)
+ uv_free_interface_addresses(addresses_v6, count_v6);
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return UV__ERR(errno);
}
@@ -413,27 +474,35 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
(*count)++;
}
- if (*count == 0) {
+ if (*count == 0 && count_v6 == 0) {
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return 0;
}
/* Alloc the return interface structs */
- *addresses = uv__malloc((*count + count_v6) *
+ *addresses = uv__calloc(1, (*count + count_v6) *
sizeof(uv_interface_address_t));
if (!(*addresses)) {
+ if (count_v6)
+ uv_free_interface_addresses(addresses_v6, count_v6);
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return UV_ENOMEM;
}
address = *addresses;
- /* copy over the ipv6 addresses */
- memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
- address += count_v6;
- *count += count_v6;
- uv__free(addresses_v6);
+ /* copy over the ipv6 addresses if any are found */
+ if (count_v6) {
+ memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
+ address += count_v6;
+ *count += count_v6;
+ /* free ipv6 addresses, but keep address names */
+ uv__free(addresses_v6);
+ }
+ count_names = *count;
ifr = ifc.ifc_req;
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
p = ifr;
@@ -446,6 +515,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ uv_free_interface_addresses(*addresses, count_names);
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return UV_ENOSYS;
}
@@ -455,22 +526,43 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* All conditions above must match count loop */
- address->name = uv__strdup(p->ifr_name);
+ i = 0;
+ /* Ignore EBCDIC space (0x40) padding in name */
+ while (i < ARRAY_SIZE(p->ifr_name) &&
+ p->ifr_name[i] != 0x40 &&
+ p->ifr_name[i] != 0)
+ ++i;
+ address->name = uv__malloc(i + 1);
+ if (address->name == NULL) {
+ uv_free_interface_addresses(*addresses, count_names);
+ uv__free(ifc.ifc_req);
+ uv__close(sockfd);
+ return UV_ENOMEM;
+ }
+ memcpy(address->name, p->ifr_name, i);
+ address->name[i] = '\0';
+ __e2a_s(address->name);
+ count_names++;
+
+ address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
- if (p->ifr_addr.sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
+ if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
+ uv_free_interface_addresses(*addresses, count_names);
+ uv__free(ifc.ifc_req);
+ uv__close(sockfd);
+ return UV__ERR(errno);
}
+ address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
+ address->netmask.netmask4.sin_family = AF_INET;
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
- memset(address->phys_addr, 0, sizeof(address->phys_addr));
address++;
}
#undef ADDR_SIZE
#undef MAX
+ uv__free(ifc.ifc_req);
uv__close(sockfd);
return 0;
}
@@ -529,27 +621,17 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
}
-void uv__fs_event_close(uv_fs_event_t* handle) {
- uv_fs_event_stop(handle);
-}
-
-
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
return 0;
}
-int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
- const char* filename, unsigned int flags) {
+static int os390_regfileint(uv_fs_event_t* handle, char* path) {
uv__os390_epoll* ep;
_RFIS reg_struct;
- char* path;
int rc;
- if (uv__is_active(handle))
- return UV_EINVAL;
-
ep = handle->loop->ep;
assert(ep->msg_queue != -1);
@@ -558,25 +640,44 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
reg_struct.__rfis_type = 1;
memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle));
+ rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
+ if (rc != 0)
+ return UV__ERR(errno);
+
+ memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
+ sizeof(handle->rfis_rftok));
+
+ return 0;
+}
+
+
+int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
+ const char* filename, unsigned int flags) {
+ char* path;
+ int rc;
+
+ if (uv__is_active(handle))
+ return UV_EINVAL;
+
path = uv__strdup(filename);
if (path == NULL)
return UV_ENOMEM;
- rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
- if (rc != 0)
- return UV__ERR(errno);
+ rc = os390_regfileint(handle, path);
+ if (rc != 0) {
+ uv__free(path);
+ return rc;
+ }
uv__handle_start(handle);
handle->path = path;
handle->cb = cb;
- memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
- sizeof(handle->rfis_rftok));
return 0;
}
-int uv_fs_event_stop(uv_fs_event_t* handle) {
+int uv__fs_event_stop(uv_fs_event_t* handle) {
uv__os390_epoll* ep;
_RFIS reg_struct;
int rc;
@@ -602,12 +703,40 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
if (rc != 0 && errno != EALREADY && errno != ENOENT)
abort();
+ if (handle->path != NULL) {
+ uv__free(handle->path);
+ handle->path = NULL;
+ }
+
+ if (rc != 0 && errno == EALREADY)
+ return -1;
+
uv__handle_stop(handle);
return 0;
}
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+ uv__fs_event_stop(handle);
+ return 0;
+}
+
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+ /*
+ * If we were unable to unregister file interest here, then it is most likely
+ * that there is a pending queued change notification. When this happens, we
+ * don't want to complete the close as it will free the underlying memory for
+ * the handle, causing a use-after-free problem when the event is processed.
+ * We defer the final cleanup until after the event is consumed in
+ * os390_message_queue_handler().
+ */
+ if (uv__fs_event_stop(handle) == 0)
+ uv__make_close_pending((uv_handle_t*) handle);
+}
+
+
static int os390_message_queue_handler(uv__os390_epoll* ep) {
uv_fs_event_t* handle;
int msglen;
@@ -628,7 +757,15 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) {
events = 0;
if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE)
events = UV_CHANGE;
- else if (msg.__rfim_event == _RFIM_RENAME)
+ else if (msg.__rfim_event == _RFIM_RENAME || msg.__rfim_event == _RFIM_UNLINK)
+ events = UV_RENAME;
+ else if (msg.__rfim_event == 156)
+ /* TODO(gabylb): zos - this event should not happen, need to investigate.
+ *
+ * This event seems to occur when the watched file is [re]moved, or an
+ * editor (like vim) renames then creates the file on save (for vim, that's
+ * when backupcopy=no|auto).
+ */
events = UV_RENAME;
else
/* Some event that we are not interested in. */
@@ -639,6 +776,26 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) {
*/
__a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok));
handle = *(uv_fs_event_t**)(msg.__rfim_utok);
+ assert(handle != NULL);
+
+ assert((handle->flags & UV_HANDLE_CLOSED) == 0);
+ if (uv__is_closing(handle)) {
+ uv__handle_stop(handle);
+ uv__make_close_pending((uv_handle_t*) handle);
+ return 0;
+ } else if (handle->path == NULL) {
+ /* _RFIS_UNREG returned EALREADY. */
+ uv__handle_stop(handle);
+ return 0;
+ }
+
+ /* The file is implicitly unregistered when the change notification is
+ * sent, only one notification is sent per registration. So we need to
+ * re-register interest in a file after each change notification we
+ * receive.
+ */
+ assert(handle->path != NULL);
+ os390_regfileint(handle, handle->path);
handle->cb(handle, uv__basename_r(handle->path), events, 0);
return 1;
}
@@ -650,6 +807,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
struct epoll_event* pe;
struct epoll_event e;
uv__os390_epoll* ep;
+ int have_signals;
int real_timeout;
QUEUE* q;
uv__io_t* w;
@@ -712,6 +870,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
count = 48; /* Benchmarks suggest this gives the best throughput. */
real_timeout = timeout;
int nevents = 0;
+ have_signals = 0;
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
reset_timeout = 1;
@@ -796,6 +955,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
ep = loop->ep;
if (pe->is_msg) {
os390_message_queue_handler(ep);
+ nevents++;
continue;
}
@@ -825,19 +985,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
pe->events |= w->pevents & (POLLIN | POLLOUT);
if (pe->events != 0) {
- uv__metrics_update_idle_time(loop);
- w->cb(loop, w, pe->events);
+ /* Run signal watchers last. This also affects child process watchers
+ * because those are implemented in terms of signal watchers.
+ */
+ if (w == &loop->signal_io_watcher) {
+ have_signals = 1;
+ } else {
+ uv__metrics_update_idle_time(loop);
+ w->cb(loop, w, pe->events);
+ }
nevents++;
}
}
- loop->watchers[loop->nwatchers] = NULL;
- loop->watchers[loop->nwatchers + 1] = NULL;
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
}
+ if (have_signals != 0) {
+ uv__metrics_update_idle_time(loop);
+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+ }
+
+ loop->watchers[loop->nwatchers] = NULL;
+ loop->watchers[loop->nwatchers + 1] = NULL;
+
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
@@ -872,6 +1048,5 @@ int uv__io_fork(uv_loop_t* loop) {
*/
loop->ep = NULL;
- uv__platform_loop_delete(loop);
return uv__platform_loop_init(loop);
}
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index fc7c4eae8..e9b88c1f1 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -49,7 +49,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Already bound? */
if (uv__stream_fd(handle) >= 0)
return UV_EINVAL;
-
+ if (uv__is_closing(handle)) {
+ return UV_EINVAL;
+ }
/* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = uv__strdup(name);
if (pipe_fname == NULL)
@@ -89,7 +91,7 @@ err_socket:
}
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
+int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
return UV_EINVAL;
@@ -317,7 +319,7 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
if (handle->accepted_fd == -1)
return UV_UNKNOWN_HANDLE;
else
- return uv__handle_type(handle->accepted_fd);
+ return uv_guess_handle(handle->accepted_fd);
}
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 2af2088f9..0de5c4695 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -27,6 +27,7 @@
#include <assert.h>
#include <errno.h>
#include <signal.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -35,9 +36,22 @@
#include <poll.h>
#include <sched.h>
-#if defined(__APPLE__) && !TARGET_OS_IPHONE
+#if defined(__APPLE__)
+# include <spawn.h>
+# include <paths.h>
+# include <sys/kauth.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <dlfcn.h>
# include <crt_externs.h>
+# include <xlocale.h>
# define environ (*_NSGetEnviron())
+
+/* macOS 10.14 back does not define this constant */
+# ifndef POSIX_SPAWN_SETSID
+# define POSIX_SPAWN_SETSID 1024
+# endif
+
#else
extern char **environ;
#endif
@@ -61,21 +75,35 @@ extern char **environ;
#endif
#endif
+#if defined(__APPLE__) || \
+ defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+#include <sys/event.h>
+#else
+#define UV_USE_SIGCHLD
+#endif
+
+#ifdef UV_USE_SIGCHLD
static void uv__chld(uv_signal_t* handle, int signum) {
+ assert(signum == SIGCHLD);
+ uv__wait_children(handle->loop);
+}
+#endif
+
+void uv__wait_children(uv_loop_t* loop) {
uv_process_t* process;
- uv_loop_t* loop;
int exit_status;
int term_signal;
int status;
+ int options;
pid_t pid;
QUEUE pending;
QUEUE* q;
QUEUE* h;
- assert(signum == SIGCHLD);
-
QUEUE_INIT(&pending);
- loop = handle->loop;
h = &loop->process_handles;
q = QUEUE_HEAD(h);
@@ -83,19 +111,33 @@ static void uv__chld(uv_signal_t* handle, int signum) {
process = QUEUE_DATA(q, uv_process_t, queue);
q = QUEUE_NEXT(q);
+#ifndef UV_USE_SIGCHLD
+ if ((process->flags & UV_HANDLE_REAP) == 0)
+ continue;
+ options = 0;
+ process->flags &= ~UV_HANDLE_REAP;
+#else
+ options = WNOHANG;
+#endif
+
do
- pid = waitpid(process->pid, &status, WNOHANG);
+ pid = waitpid(process->pid, &status, options);
while (pid == -1 && errno == EINTR);
- if (pid == 0)
+#ifdef UV_USE_SIGCHLD
+ if (pid == 0) /* Not yet exited */
continue;
+#endif
if (pid == -1) {
if (errno != ECHILD)
abort();
+ /* The child died, and we missed it. This probably means someone else
+ * stole the waitpid from us. Handle this by not handling it at all. */
continue;
}
+ assert(pid == process->pid);
process->status = status;
QUEUE_REMOVE(&process->queue);
QUEUE_INSERT_TAIL(&pending, &process->queue);
@@ -206,16 +248,14 @@ static void uv__write_int(int fd, int val) {
n = write(fd, &val, sizeof(val));
while (n == -1 && errno == EINTR);
- if (n == -1 && errno == EPIPE)
- return; /* parent process has quit */
-
- assert(n == sizeof(val));
+ /* The write might have failed (e.g. if the parent process has died),
+ * but we have nothing left but to _exit ourself now too. */
+ _exit(127);
}
static void uv__write_errno(int error_fd) {
uv__write_int(error_fd, UV__ERR(errno));
- _exit(127);
}
@@ -273,22 +313,31 @@ static void uv__process_child_init(const uv_process_options_t* options,
use_fd = pipes[fd][1];
if (use_fd < 0 || use_fd >= fd)
continue;
+#ifdef F_DUPFD_CLOEXEC /* POSIX 2008 */
+ pipes[fd][1] = fcntl(use_fd, F_DUPFD_CLOEXEC, stdio_count);
+#else
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
+#endif
if (pipes[fd][1] == -1)
uv__write_errno(error_fd);
+#ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */
+ n = uv__cloexec(pipes[fd][1], 1);
+ if (n)
+ uv__write_int(error_fd, n);
+#endif
}
for (fd = 0; fd < stdio_count; fd++) {
- close_fd = pipes[fd][0];
+ close_fd = -1;
use_fd = pipes[fd][1];
if (use_fd < 0) {
if (fd >= 3)
continue;
else {
- /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
- * set
- */
+ /* Redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
+ * set. */
+ uv__close_nocheckstdio(fd); /* Free up fd, if it happens to be open. */
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
close_fd = use_fd;
@@ -297,28 +346,27 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
}
- if (fd == use_fd)
- uv__cloexec_fcntl(use_fd, 0);
- else
+ if (fd == use_fd) {
+ if (close_fd == -1) {
+ n = uv__cloexec(use_fd, 0);
+ if (n)
+ uv__write_int(error_fd, n);
+ }
+ }
+ else {
fd = dup2(use_fd, fd);
+ }
if (fd == -1)
uv__write_errno(error_fd);
- if (fd <= 2)
+ if (fd <= 2 && close_fd == -1)
uv__nonblock_fcntl(fd, 0);
if (close_fd >= stdio_count)
uv__close(close_fd);
}
- for (fd = 0; fd < stdio_count; fd++) {
- use_fd = pipes[fd][1];
-
- if (use_fd >= stdio_count)
- uv__close(use_fd);
- }
-
if (options->cwd != NULL && chdir(options->cwd))
uv__write_errno(error_fd);
@@ -361,9 +409,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
#endif
#endif
- if (options->env != NULL) {
+ if (options->env != NULL)
environ = options->env;
- }
/* Reset signal mask just before exec. */
sigemptyset(&signewset);
@@ -377,11 +424,555 @@ static void uv__process_child_init(const uv_process_options_t* options,
#endif
uv__write_errno(error_fd);
- abort();
}
#endif
+#if defined(__APPLE__)
+typedef struct uv__posix_spawn_fncs_tag {
+ struct {
+ int (*addchdir_np)(const posix_spawn_file_actions_t *, const char *);
+ } file_actions;
+} uv__posix_spawn_fncs_t;
+
+
+static uv_once_t posix_spawn_init_once = UV_ONCE_INIT;
+static uv__posix_spawn_fncs_t posix_spawn_fncs;
+static int posix_spawn_can_use_setsid;
+
+
+static void uv__spawn_init_posix_spawn_fncs(void) {
+ /* Try to locate all non-portable functions at runtime */
+ posix_spawn_fncs.file_actions.addchdir_np =
+ dlsym(RTLD_DEFAULT, "posix_spawn_file_actions_addchdir_np");
+}
+
+
+static void uv__spawn_init_can_use_setsid(void) {
+ int which[] = {CTL_KERN, KERN_OSRELEASE};
+ unsigned major;
+ unsigned minor;
+ unsigned patch;
+ char buf[256];
+ size_t len;
+
+ len = sizeof(buf);
+ if (sysctl(which, ARRAY_SIZE(which), buf, &len, NULL, 0))
+ return;
+
+ /* NULL specifies to use LC_C_LOCALE */
+ if (3 != sscanf_l(buf, NULL, "%u.%u.%u", &major, &minor, &patch))
+ return;
+
+ posix_spawn_can_use_setsid = (major >= 19); /* macOS Catalina */
+}
+
+
+static void uv__spawn_init_posix_spawn(void) {
+ /* Init handles to all potentially non-defined functions */
+ uv__spawn_init_posix_spawn_fncs();
+
+ /* Init feature detection for POSIX_SPAWN_SETSID flag */
+ uv__spawn_init_can_use_setsid();
+}
+
+
+static int uv__spawn_set_posix_spawn_attrs(
+ posix_spawnattr_t* attrs,
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs,
+ const uv_process_options_t* options) {
+ int err;
+ unsigned int flags;
+ sigset_t signal_set;
+
+ err = posix_spawnattr_init(attrs);
+ if (err != 0) {
+ /* If initialization fails, no need to de-init, just return */
+ return err;
+ }
+
+ if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
+ /* kauth_cred_issuser currently requires exactly uid == 0 for these
+ * posixspawn_attrs (set_groups_np, setuid_np, setgid_np), which deviates
+ * from the normal specification of setuid (which also uses euid), and they
+ * are also undocumented syscalls, so we do not use them. */
+ err = ENOSYS;
+ goto error;
+ }
+
+ /* Set flags for spawn behavior
+ * 1) POSIX_SPAWN_CLOEXEC_DEFAULT: (Apple Extension) All descriptors in the
+ * parent will be treated as if they had been created with O_CLOEXEC. The
+ * only fds that will be passed on to the child are those manipulated by
+ * the file actions
+ * 2) POSIX_SPAWN_SETSIGDEF: Signals mentioned in spawn-sigdefault in the
+ * spawn attributes will be reset to behave as their default
+ * 3) POSIX_SPAWN_SETSIGMASK: Signal mask will be set to the value of
+ * spawn-sigmask in attributes
+ * 4) POSIX_SPAWN_SETSID: Make the process a new session leader if a detached
+ * session was requested. */
+ flags = POSIX_SPAWN_CLOEXEC_DEFAULT |
+ POSIX_SPAWN_SETSIGDEF |
+ POSIX_SPAWN_SETSIGMASK;
+ if (options->flags & UV_PROCESS_DETACHED) {
+ /* If running on a version of macOS where this flag is not supported,
+ * revert back to the fork/exec flow. Otherwise posix_spawn will
+ * silently ignore the flag. */
+ if (!posix_spawn_can_use_setsid) {
+ err = ENOSYS;
+ goto error;
+ }
+
+ flags |= POSIX_SPAWN_SETSID;
+ }
+ err = posix_spawnattr_setflags(attrs, flags);
+ if (err != 0)
+ goto error;
+
+ /* Reset all signal the child to their default behavior */
+ sigfillset(&signal_set);
+ err = posix_spawnattr_setsigdefault(attrs, &signal_set);
+ if (err != 0)
+ goto error;
+
+ /* Reset the signal mask for all signals */
+ sigemptyset(&signal_set);
+ err = posix_spawnattr_setsigmask(attrs, &signal_set);
+ if (err != 0)
+ goto error;
+
+ return err;
+
+error:
+ (void) posix_spawnattr_destroy(attrs);
+ return err;
+}
+
+
+static int uv__spawn_set_posix_spawn_file_actions(
+ posix_spawn_file_actions_t* actions,
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs,
+ const uv_process_options_t* options,
+ int stdio_count,
+ int (*pipes)[2]) {
+ int fd;
+ int fd2;
+ int use_fd;
+ int err;
+
+ err = posix_spawn_file_actions_init(actions);
+ if (err != 0) {
+ /* If initialization fails, no need to de-init, just return */
+ return err;
+ }
+
+ /* Set the current working directory if requested */
+ if (options->cwd != NULL) {
+ if (posix_spawn_fncs->file_actions.addchdir_np == NULL) {
+ err = ENOSYS;
+ goto error;
+ }
+
+ err = posix_spawn_fncs->file_actions.addchdir_np(actions, options->cwd);
+ if (err != 0)
+ goto error;
+ }
+
+ /* Do not return ENOSYS after this point, as we may mutate pipes. */
+
+ /* First duplicate low numbered fds, since it's not safe to duplicate them,
+ * they could get replaced. Example: swapping stdout and stderr; without
+ * this fd 2 (stderr) would be duplicated into fd 1, thus making both
+ * stdout and stderr go to the same fd, which was not the intention. */
+ for (fd = 0; fd < stdio_count; fd++) {
+ use_fd = pipes[fd][1];
+ if (use_fd < 0 || use_fd >= fd)
+ continue;
+ use_fd = stdio_count;
+ for (fd2 = 0; fd2 < stdio_count; fd2++) {
+ /* If we were not setting POSIX_SPAWN_CLOEXEC_DEFAULT, we would need to
+ * also consider whether fcntl(fd, F_GETFD) returned without the
+ * FD_CLOEXEC flag set. */
+ if (pipes[fd2][1] == use_fd) {
+ use_fd++;
+ fd2 = 0;
+ }
+ }
+ err = posix_spawn_file_actions_adddup2(
+ actions,
+ pipes[fd][1],
+ use_fd);
+ assert(err != ENOSYS);
+ if (err != 0)
+ goto error;
+ pipes[fd][1] = use_fd;
+ }
+
+ /* Second, move the descriptors into their respective places */
+ for (fd = 0; fd < stdio_count; fd++) {
+ use_fd = pipes[fd][1];
+ if (use_fd < 0) {
+ if (fd >= 3)
+ continue;
+ else {
+ /* If ignored, redirect to (or from) /dev/null, */
+ err = posix_spawn_file_actions_addopen(
+ actions,
+ fd,
+ "/dev/null",
+ fd == 0 ? O_RDONLY : O_RDWR,
+ 0);
+ assert(err != ENOSYS);
+ if (err != 0)
+ goto error;
+ continue;
+ }
+ }
+
+ if (fd == use_fd)
+ err = posix_spawn_file_actions_addinherit_np(actions, fd);
+ else
+ err = posix_spawn_file_actions_adddup2(actions, use_fd, fd);
+ assert(err != ENOSYS);
+ if (err != 0)
+ goto error;
+
+ /* Make sure the fd is marked as non-blocking (state shared between child
+ * and parent). */
+ uv__nonblock_fcntl(use_fd, 0);
+ }
+
+ /* Finally, close all the superfluous descriptors */
+ for (fd = 0; fd < stdio_count; fd++) {
+ use_fd = pipes[fd][1];
+ if (use_fd < stdio_count)
+ continue;
+
+ /* Check if we already closed this. */
+ for (fd2 = 0; fd2 < fd; fd2++) {
+ if (pipes[fd2][1] == use_fd)
+ break;
+ }
+ if (fd2 < fd)
+ continue;
+
+ err = posix_spawn_file_actions_addclose(actions, use_fd);
+ assert(err != ENOSYS);
+ if (err != 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ (void) posix_spawn_file_actions_destroy(actions);
+ return err;
+}
+
+char* uv__spawn_find_path_in_env(char** env) {
+ char** env_iterator;
+ const char path_var[] = "PATH=";
+
+ /* Look for an environment variable called PATH in the
+ * provided env array, and return its value if found */
+ for (env_iterator = env; *env_iterator != NULL; env_iterator++) {
+ if (strncmp(*env_iterator, path_var, sizeof(path_var) - 1) == 0) {
+ /* Found "PATH=" at the beginning of the string */
+ return *env_iterator + sizeof(path_var) - 1;
+ }
+ }
+
+ return NULL;
+}
+
+
+static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options,
+ posix_spawnattr_t* attrs,
+ posix_spawn_file_actions_t* actions,
+ pid_t* pid) {
+ const char *p;
+ const char *z;
+ const char *path;
+ size_t l;
+ size_t k;
+ int err;
+ int seen_eacces;
+
+ path = NULL;
+ err = -1;
+ seen_eacces = 0;
+
+ /* Short circuit for erroneous case */
+ if (options->file == NULL)
+ return ENOENT;
+
+ /* The environment for the child process is that of the parent unless overriden
+ * by options->env */
+ char** env = environ;
+ if (options->env != NULL)
+ env = options->env;
+
+ /* If options->file contains a slash, posix_spawn/posix_spawnp should behave
+ * the same, and do not involve PATH resolution at all. The libc
+ * `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it
+ * here, per https://github.com/libuv/libuv/pull/3583. */
+ if (strchr(options->file, '/') != NULL) {
+ do
+ err = posix_spawn(pid, options->file, actions, attrs, options->args, env);
+ while (err == EINTR);
+ return err;
+ }
+
+ /* Look for the definition of PATH in the provided env */
+ path = uv__spawn_find_path_in_env(env);
+
+ /* The following resolution logic (execvpe emulation) is copied from
+ * https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c
+ * and adapted to work for our specific usage */
+
+ /* If no path was provided in env, use the default value
+ * to look for the executable */
+ if (path == NULL)
+ path = _PATH_DEFPATH;
+
+ k = strnlen(options->file, NAME_MAX + 1);
+ if (k > NAME_MAX)
+ return ENAMETOOLONG;
+
+ l = strnlen(path, PATH_MAX - 1) + 1;
+
+ for (p = path;; p = z) {
+ /* Compose the new process file from the entry in the PATH
+ * environment variable and the actual file name */
+ char b[PATH_MAX + NAME_MAX];
+ z = strchr(p, ':');
+ if (!z)
+ z = p + strlen(p);
+ if ((size_t)(z - p) >= l) {
+ if (!*z++)
+ break;
+
+ continue;
+ }
+ memcpy(b, p, z - p);
+ b[z - p] = '/';
+ memcpy(b + (z - p) + (z > p), options->file, k + 1);
+
+ /* Try to spawn the new process file. If it fails with ENOENT, the
+ * new process file is not in this PATH entry, continue with the next
+ * PATH entry. */
+ do
+ err = posix_spawn(pid, b, actions, attrs, options->args, env);
+ while (err == EINTR);
+
+ switch (err) {
+ case EACCES:
+ seen_eacces = 1;
+ break; /* continue search */
+ case ENOENT:
+ case ENOTDIR:
+ break; /* continue search */
+ default:
+ return err;
+ }
+
+ if (!*z++)
+ break;
+ }
+
+ if (seen_eacces)
+ return EACCES;
+ return err;
+}
+
+
+static int uv__spawn_and_init_child_posix_spawn(
+ const uv_process_options_t* options,
+ int stdio_count,
+ int (*pipes)[2],
+ pid_t* pid,
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs) {
+ int err;
+ posix_spawnattr_t attrs;
+ posix_spawn_file_actions_t actions;
+
+ err = uv__spawn_set_posix_spawn_attrs(&attrs, posix_spawn_fncs, options);
+ if (err != 0)
+ goto error;
+
+ /* This may mutate pipes. */
+ err = uv__spawn_set_posix_spawn_file_actions(&actions,
+ posix_spawn_fncs,
+ options,
+ stdio_count,
+ pipes);
+ if (err != 0) {
+ (void) posix_spawnattr_destroy(&attrs);
+ goto error;
+ }
+
+ /* Try to spawn options->file resolving in the provided environment
+ * if any */
+ err = uv__spawn_resolve_and_spawn(options, &attrs, &actions, pid);
+ assert(err != ENOSYS);
+
+ /* Destroy the actions/attributes */
+ (void) posix_spawn_file_actions_destroy(&actions);
+ (void) posix_spawnattr_destroy(&attrs);
+
+error:
+ /* In an error situation, the attributes and file actions are
+ * already destroyed, only the happy path requires cleanup */
+ return UV__ERR(err);
+}
+#endif
+
+static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
+ int stdio_count,
+ int (*pipes)[2],
+ int error_fd,
+ pid_t* pid) {
+ sigset_t signewset;
+ sigset_t sigoldset;
+
+ /* Start the child with most signals blocked, to avoid any issues before we
+ * can reset them, but allow program failures to exit (and not hang). */
+ sigfillset(&signewset);
+ sigdelset(&signewset, SIGKILL);
+ sigdelset(&signewset, SIGSTOP);
+ sigdelset(&signewset, SIGTRAP);
+ sigdelset(&signewset, SIGSEGV);
+ sigdelset(&signewset, SIGBUS);
+ sigdelset(&signewset, SIGILL);
+ sigdelset(&signewset, SIGSYS);
+ sigdelset(&signewset, SIGABRT);
+ if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
+ abort();
+
+ *pid = fork();
+
+ if (*pid == 0) {
+ /* Fork succeeded, in the child process */
+ uv__process_child_init(options, stdio_count, pipes, error_fd);
+ abort();
+ }
+
+ if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
+ abort();
+
+ if (*pid == -1)
+ /* Failed to fork */
+ return UV__ERR(errno);
+
+ /* Fork succeeded, in the parent process */
+ return 0;
+}
+
+static int uv__spawn_and_init_child(
+ uv_loop_t* loop,
+ const uv_process_options_t* options,
+ int stdio_count,
+ int (*pipes)[2],
+ pid_t* pid) {
+ int signal_pipe[2] = { -1, -1 };
+ int status;
+ int err;
+ int exec_errorno;
+ ssize_t r;
+
+#if defined(__APPLE__)
+ uv_once(&posix_spawn_init_once, uv__spawn_init_posix_spawn);
+
+ /* Special child process spawn case for macOS Big Sur (11.0) onwards
+ *
+ * Big Sur introduced a significant performance degradation on a call to
+ * fork/exec when the process has many pages mmaped in with MAP_JIT, like, say
+ * a javascript interpreter. Electron-based applications, for example,
+ * are impacted; though the magnitude of the impact depends on how much the
+ * app relies on subprocesses.
+ *
+ * On macOS, though, posix_spawn is implemented in a way that does not
+ * exhibit the problem. This block implements the forking and preparation
+ * logic with posix_spawn and its related primitives. It also takes advantage of
+ * the macOS extension POSIX_SPAWN_CLOEXEC_DEFAULT that makes impossible to
+ * leak descriptors to the child process. */
+ err = uv__spawn_and_init_child_posix_spawn(options,
+ stdio_count,
+ pipes,
+ pid,
+ &posix_spawn_fncs);
+
+ /* The posix_spawn flow will return UV_ENOSYS if any of the posix_spawn_x_np
+ * non-standard functions is both _needed_ and _undefined_. In those cases,
+ * default back to the fork/execve strategy. For all other errors, just fail. */
+ if (err != UV_ENOSYS)
+ return err;
+
+#endif
+
+ /* This pipe is used by the parent to wait until
+ * the child has called `execve()`. We need this
+ * to avoid the following race condition:
+ *
+ * if ((pid = fork()) > 0) {
+ * kill(pid, SIGTERM);
+ * }
+ * else if (pid == 0) {
+ * execve("/bin/cat", argp, envp);
+ * }
+ *
+ * The parent sends a signal immediately after forking.
+ * Since the child may not have called `execve()` yet,
+ * there is no telling what process receives the signal,
+ * our fork or /bin/cat.
+ *
+ * To avoid ambiguity, we create a pipe with both ends
+ * marked close-on-exec. Then, after the call to `fork()`,
+ * the parent polls the read end until it EOFs or errors with EPIPE.
+ */
+ err = uv__make_pipe(signal_pipe, 0);
+ if (err)
+ return err;
+
+ /* Acquire write lock to prevent opening new fds in worker threads */
+ uv_rwlock_wrlock(&loop->cloexec_lock);
+
+ err = uv__spawn_and_init_child_fork(options, stdio_count, pipes, signal_pipe[1], pid);
+
+ /* Release lock in parent process */
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
+
+ uv__close(signal_pipe[1]);
+
+ if (err == 0) {
+ do
+ r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
+ while (r == -1 && errno == EINTR);
+
+ if (r == 0)
+ ; /* okay, EOF */
+ else if (r == sizeof(exec_errorno)) {
+ do
+ err = waitpid(*pid, &status, 0); /* okay, read errorno */
+ while (err == -1 && errno == EINTR);
+ assert(err == *pid);
+ err = exec_errorno;
+ } else if (r == -1 && errno == EPIPE) {
+ /* Something unknown happened to our child before spawn */
+ do
+ err = waitpid(*pid, &status, 0); /* okay, got EPIPE */
+ while (err == -1 && errno == EINTR);
+ assert(err == *pid);
+ err = UV_EPIPE;
+ } else
+ abort();
+ }
+
+ uv__close_nocheckstdio(signal_pipe[0]);
+
+ return err;
+}
+
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,
const uv_process_options_t* options) {
@@ -389,18 +980,13 @@ int uv_spawn(uv_loop_t* loop,
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
return UV_ENOSYS;
#else
- sigset_t signewset;
- sigset_t sigoldset;
- int signal_pipe[2] = { -1, -1 };
int pipes_storage[8][2];
int (*pipes)[2];
int stdio_count;
- ssize_t r;
pid_t pid;
int err;
int exec_errorno;
int i;
- int status;
if (options->cpumask != NULL) {
#ifndef CMAKE_BOOTSTRAP
@@ -427,6 +1013,7 @@ int uv_spawn(uv_loop_t* loop,
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
QUEUE_INIT(&process->queue);
+ process->status = 0;
stdio_count = options->stdio_count;
if (stdio_count < 3)
@@ -451,92 +1038,43 @@ int uv_spawn(uv_loop_t* loop,
goto error;
}
- /* This pipe is used by the parent to wait until
- * the child has called `execve()`. We need this
- * to avoid the following race condition:
- *
- * if ((pid = fork()) > 0) {
- * kill(pid, SIGTERM);
- * }
- * else if (pid == 0) {
- * execve("/bin/cat", argp, envp);
- * }
- *
- * The parent sends a signal immediately after forking.
- * Since the child may not have called `execve()` yet,
- * there is no telling what process receives the signal,
- * our fork or /bin/cat.
- *
- * To avoid ambiguity, we create a pipe with both ends
- * marked close-on-exec. Then, after the call to `fork()`,
- * the parent polls the read end until it EOFs or errors with EPIPE.
- */
- err = uv__make_pipe(signal_pipe, 0);
- if (err)
- goto error;
-
+#ifdef UV_USE_SIGCHLD
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
+#endif
- /* Acquire write lock to prevent opening new fds in worker threads */
- uv_rwlock_wrlock(&loop->cloexec_lock);
-
- /* Start the child with most signals blocked, to avoid any issues before we
- * can reset them, but allow program failures to exit (and not hang). */
- sigfillset(&signewset);
- sigdelset(&signewset, SIGKILL);
- sigdelset(&signewset, SIGSTOP);
- sigdelset(&signewset, SIGTRAP);
- sigdelset(&signewset, SIGSEGV);
- sigdelset(&signewset, SIGBUS);
- sigdelset(&signewset, SIGILL);
- sigdelset(&signewset, SIGSYS);
- sigdelset(&signewset, SIGABRT);
- if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
- abort();
-
- pid = fork();
- if (pid == -1)
- err = UV__ERR(errno);
-
- if (pid == 0)
- uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
-
- if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
- abort();
+ /* Spawn the child */
+ exec_errorno = uv__spawn_and_init_child(loop, options, stdio_count, pipes, &pid);
- /* Release lock in parent process */
- uv_rwlock_wrunlock(&loop->cloexec_lock);
+#if 0
+ /* This runs into a nodejs issue (it expects initialized streams, even if the
+ * exec failed).
+ * See https://github.com/libuv/libuv/pull/3107#issuecomment-782482608 */
+ if (exec_errorno != 0)
+ goto error;
+#endif
- uv__close(signal_pipe[1]);
+ /* Activate this handle if exec() happened successfully, even if we later
+ * fail to open a stdio handle. This ensures we can eventually reap the child
+ * with waitpid. */
+ if (exec_errorno == 0) {
+#ifndef UV_USE_SIGCHLD
+ struct kevent event;
+ EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0);
+ if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) {
+ if (errno != ESRCH)
+ abort();
+ /* Process already exited. Call waitpid on the next loop iteration. */
+ process->flags |= UV_HANDLE_REAP;
+ loop->flags |= UV_LOOP_REAP_CHILDREN;
+ }
+#endif
- if (pid == -1) {
- uv__close(signal_pipe[0]);
- goto error;
+ process->pid = pid;
+ process->exit_cb = options->exit_cb;
+ QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
+ uv__handle_start(process);
}
- process->status = 0;
- exec_errorno = 0;
- do
- r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
- while (r == -1 && errno == EINTR);
-
- if (r == 0)
- ; /* okay, EOF */
- else if (r == sizeof(exec_errorno)) {
- do
- err = waitpid(pid, &status, 0); /* okay, read errorno */
- while (err == -1 && errno == EINTR);
- assert(err == pid);
- } else if (r == -1 && errno == EPIPE) {
- do
- err = waitpid(pid, &status, 0); /* okay, got EPIPE */
- while (err == -1 && errno == EINTR);
- assert(err == pid);
- } else
- abort();
-
- uv__close_nocheckstdio(signal_pipe[0]);
-
for (i = 0; i < options->stdio_count; i++) {
err = uv__process_open_stream(options->stdio + i, pipes[i]);
if (err == 0)
@@ -548,15 +1086,6 @@ int uv_spawn(uv_loop_t* loop,
goto error;
}
- /* Only activate this handle if exec() happened successfully */
- if (exec_errorno == 0) {
- QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
- uv__handle_start(process);
- }
-
- process->pid = pid;
- process->exit_cb = options->exit_cb;
-
if (pipes != pipes_storage)
uv__free(pipes);
@@ -589,9 +1118,16 @@ int uv_process_kill(uv_process_t* process, int signum) {
int uv_kill(int pid, int signum) {
- if (kill(pid, signum))
+ if (kill(pid, signum)) {
+#if defined(__MVS__)
+ /* EPERM is returned if the process is a zombie. */
+ siginfo_t infop;
+ if (errno == EPERM &&
+ waitid(P_PID, pid, &infop, WNOHANG | WNOWAIT | WEXITED) == 0)
+ return 0;
+#endif
return UV__ERR(errno);
- else
+ } else
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 52e2b9a1d..1ce75257b 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -66,6 +66,7 @@ static void uv__read(uv_stream_t* stream);
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
static void uv__write_callbacks(uv_stream_t* stream);
static size_t uv__write_req_size(uv_write_t* req);
+static void uv__drain(uv_stream_t* stream);
void uv__stream_init(uv_loop_t* loop,
@@ -453,17 +454,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
-
- if (stream->shutdown_req) {
- /* The ECANCELED error code is a lie, the shutdown(2) syscall is a
- * fait accompli at this point. Maybe we should revisit this in v0.11.
- * A possible reason for leaving it unchanged is that it informs the
- * callee that the handle has been destroyed.
- */
- uv__req_unregister(stream->loop, stream->shutdown_req);
- stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
- stream->shutdown_req = NULL;
- }
+ uv__drain(stream);
assert(stream->write_queue_size == 0);
}
@@ -641,14 +632,16 @@ done:
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
int err;
-
+ if (uv__is_closing(stream)) {
+ return UV_EINVAL;
+ }
switch (stream->type) {
case UV_TCP:
- err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
+ err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
+ err = uv__pipe_listen((uv_pipe_t*)stream, backlog, cb);
break;
default:
@@ -667,25 +660,30 @@ static void uv__drain(uv_stream_t* stream) {
int err;
assert(QUEUE_EMPTY(&stream->write_queue));
- uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
- uv__stream_osx_interrupt_select(stream);
+ if (!(stream->flags & UV_HANDLE_CLOSING)) {
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
+ uv__stream_osx_interrupt_select(stream);
+ }
- /* Shutdown? */
- if ((stream->flags & UV_HANDLE_SHUTTING) &&
- !(stream->flags & UV_HANDLE_CLOSING) &&
- !(stream->flags & UV_HANDLE_SHUT)) {
- assert(stream->shutdown_req);
+ if (!(stream->flags & UV_HANDLE_SHUTTING))
+ return;
- req = stream->shutdown_req;
+ req = stream->shutdown_req;
+ assert(req);
+
+ if ((stream->flags & UV_HANDLE_CLOSING) ||
+ !(stream->flags & UV_HANDLE_SHUT)) {
stream->shutdown_req = NULL;
stream->flags &= ~UV_HANDLE_SHUTTING;
uv__req_unregister(stream->loop, req);
err = 0;
- if (shutdown(uv__stream_fd(stream), SHUT_WR))
+ if (stream->flags & UV_HANDLE_CLOSING)
+ /* The user destroyed the stream before we got to do the shutdown. */
+ err = UV_ECANCELED;
+ else if (shutdown(uv__stream_fd(stream), SHUT_WR))
err = UV__ERR(errno);
-
- if (err == 0)
+ else /* Success. */
stream->flags |= UV_HANDLE_SHUT;
if (req->cb != NULL)
@@ -926,7 +924,6 @@ static void uv__write(uv_stream_t* stream) {
}
req->error = n;
- /* XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events */
uv__write_req_finish(req);
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
@@ -964,49 +961,6 @@ static void uv__write_callbacks(uv_stream_t* stream) {
}
-uv_handle_type uv__handle_type(int fd) {
- struct sockaddr_storage ss;
- socklen_t sslen;
- socklen_t len;
- int type;
-
- memset(&ss, 0, sizeof(ss));
- sslen = sizeof(ss);
-
- if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
- return UV_UNKNOWN_HANDLE;
-
- len = sizeof type;
-
- if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len))
- return UV_UNKNOWN_HANDLE;
-
- if (type == SOCK_STREAM) {
-#if defined(_AIX) || defined(__DragonFly__)
- /* on AIX/DragonFly the getsockname call returns an empty sa structure
- * for sockets of type AF_UNIX. For all other types it will
- * return a properly filled in structure.
- */
- if (sslen == 0)
- return UV_NAMED_PIPE;
-#endif
- switch (ss.ss_family) {
- case AF_UNIX:
- return UV_NAMED_PIPE;
- case AF_INET:
- case AF_INET6:
- return UV_TCP;
- }
- }
-
- if (type == SOCK_DGRAM &&
- (ss.ss_family == AF_INET || ss.ss_family == AF_INET6))
- return UV_UDP;
-
- return UV_UNKNOWN_HANDLE;
-}
-
-
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
stream->flags &= ~UV_HANDLE_READING;
@@ -1278,7 +1232,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
assert(uv__stream_fd(stream) >= 0);
- /* Initialize request */
+ /* Initialize request. The `shutdown(2)` call will always be deferred until
+ * `uv__drain`, just before the callback is run. */
uv__req_init(stream->loop, req, UV_SHUTDOWN);
req->handle = stream;
req->cb = cb;
@@ -1286,8 +1241,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
stream->flags |= UV_HANDLE_SHUTTING;
stream->flags &= ~UV_HANDLE_WRITABLE;
- uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
- uv__stream_osx_interrupt_select(stream);
+ if (QUEUE_EMPTY(&stream->write_queue))
+ uv__io_feed(stream->loop, &stream->io_watcher);
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index eab2e40a6..85e4d6025 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -158,7 +158,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
sigset_t set;
uint64_t base;
uint64_t diff;
- uint64_t idle_poll;
unsigned int nfds;
unsigned int i;
int saved_errno;
@@ -428,7 +427,7 @@ void uv_loadavg(double avg[3]) {
#if defined(PORT_SOURCE_FILE)
static int uv__fs_event_rearm(uv_fs_event_t *handle) {
- if (handle->fd == -1)
+ if (handle->fd == PORT_DELETED)
return UV_EBADF;
if (port_associate(handle->loop->fs_fd,
@@ -479,6 +478,12 @@ static void uv__fs_event_read(uv_loop_t* loop,
handle = (uv_fs_event_t*) pe.portev_user;
assert((r == 0) && "unexpected port_get() error");
+ if (uv__is_closing(handle)) {
+ uv__handle_stop(handle);
+ uv__make_close_pending((uv_handle_t*) handle);
+ break;
+ }
+
events = 0;
if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED))
events |= UV_CHANGE;
@@ -546,12 +551,14 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
-int uv_fs_event_stop(uv_fs_event_t* handle) {
+static int uv__fs_event_stop(uv_fs_event_t* handle) {
+ int ret = 0;
+
if (!uv__is_active(handle))
return 0;
- if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) {
- port_dissociate(handle->loop->fs_fd,
+ if (handle->fd == PORT_LOADED) {
+ ret = port_dissociate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo);
}
@@ -560,13 +567,28 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__free(handle->path);
handle->path = NULL;
handle->fo.fo_name = NULL;
- uv__handle_stop(handle);
+ if (ret == 0)
+ uv__handle_stop(handle);
+
+ return ret;
+}
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+ (void) uv__fs_event_stop(handle);
return 0;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
- uv_fs_event_stop(handle);
+ /*
+ * If we were unable to dissociate the port here, then it is most likely
+ * that there is a pending queued event. When this happens, we don't want
+ * to complete the close as it will free the underlying memory for the
+ * handle, causing a use-after-free problem when the event is processed.
+ * We defer the final cleanup until after the event is consumed in
+ * uv__fs_event_read().
+ */
+ if (uv__fs_event_stop(handle) == 0)
+ uv__make_close_pending((uv_handle_t*) handle);
}
#else /* !defined(PORT_SOURCE_FILE) */
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index bc0fb661f..73fc657a8 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -184,14 +184,15 @@ int uv__tcp_bind(uv_tcp_t* tcp,
#endif
errno = 0;
- if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
+ err = bind(tcp->io_watcher.fd, addr, addrlen);
+ if (err == -1 && errno != EADDRINUSE) {
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
return UV_EINVAL;
return UV__ERR(errno);
}
- tcp->delayed_error = UV__ERR(errno);
+ tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0;
tcp->flags |= UV_HANDLE_BOUND;
if (addr->sa_family == AF_INET6)
@@ -320,15 +321,23 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
return UV_EINVAL;
fd = uv__stream_fd(handle);
- if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
- return UV__ERR(errno);
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) {
+ if (errno == EINVAL) {
+ /* Open Group Specifications Issue 7, 2018 edition states that
+ * EINVAL may mean the socket has been shut down already.
+ * Behavior observed on Solaris, illumos and macOS. */
+ errno = 0;
+ } else {
+ return UV__ERR(errno);
+ }
+ }
uv_close((uv_handle_t*) handle, close_cb);
return 0;
}
-int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
+int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept_cached = -1;
unsigned long flags;
int single_accept;
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index cbddf173f..5a07b027e 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -162,12 +162,46 @@ void uv_barrier_destroy(uv_barrier_t* barrier) {
#endif
-/* On MacOS, threads other than the main thread are created with a reduced
- * stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
+/* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
+ * too small to safely receive signals on.
+ *
+ * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
+ * the largest MINSIGSTKSZ of the architectures that musl supports) so
+ * let's use that as a lower bound.
*
- * On Linux, threads created by musl have a much smaller stack than threads
+ * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
+ * is between 28 and 133 KB when compiling against glibc, depending
+ * on the architecture.
+ */
+static size_t uv__min_stack_size(void) {
+ static const size_t min = 8192;
+
+#ifdef PTHREAD_STACK_MIN /* Not defined on NetBSD. */
+ if (min < (size_t) PTHREAD_STACK_MIN)
+ return PTHREAD_STACK_MIN;
+#endif /* PTHREAD_STACK_MIN */
+
+ return min;
+}
+
+
+/* On Linux, threads created by musl have a much smaller stack than threads
* created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency.
*/
+static size_t uv__default_stack_size(void) {
+#if !defined(__linux__)
+ return 0;
+#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
+ return 4 << 20; /* glibc default. */
+#else
+ return 2 << 20; /* glibc default. */
+#endif
+}
+
+
+/* On MacOS, threads other than the main thread are created with a reduced
+ * stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
+ */
size_t uv__thread_stack_size(void) {
#if defined(__APPLE__) || defined(__linux__)
struct rlimit lim;
@@ -176,34 +210,20 @@ size_t uv__thread_stack_size(void) {
* the system call wrapper invokes the wrong system call. Don't treat
* that as fatal, just use the default stack size instead.
*/
- if (0 == getrlimit(RLIMIT_STACK, &lim) && lim.rlim_cur != RLIM_INFINITY) {
- /* pthread_attr_setstacksize() expects page-aligned values. */
- lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
-
- /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
- * too small to safely receive signals on.
- *
- * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
- * the largest MINSIGSTKSZ of the architectures that musl supports) so
- * let's use that as a lower bound.
- *
- * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
- * is between 28 and 133 KB when compiling against glibc, depending
- * on the architecture.
- */
- if (lim.rlim_cur >= 8192)
- if (lim.rlim_cur >= PTHREAD_STACK_MIN)
- return lim.rlim_cur;
- }
-#endif
+ if (getrlimit(RLIMIT_STACK, &lim))
+ return uv__default_stack_size();
-#if !defined(__linux__)
- return 0;
-#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
- return 4 << 20; /* glibc default. */
-#else
- return 2 << 20; /* glibc default. */
+ if (lim.rlim_cur == RLIM_INFINITY)
+ return uv__default_stack_size();
+
+ /* pthread_attr_setstacksize() expects page-aligned values. */
+ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
+
+ if (lim.rlim_cur >= (rlim_t) uv__min_stack_size())
+ return lim.rlim_cur;
#endif
+
+ return uv__default_stack_size();
}
@@ -222,6 +242,7 @@ int uv_thread_create_ex(uv_thread_t* tid,
pthread_attr_t attr_storage;
size_t pagesize;
size_t stack_size;
+ size_t min_stack_size;
/* Used to squelch a -Wcast-function-type warning. */
union {
@@ -239,10 +260,9 @@ int uv_thread_create_ex(uv_thread_t* tid,
pagesize = (size_t)getpagesize();
/* Round up to the nearest page boundary. */
stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
-#ifdef PTHREAD_STACK_MIN
- if (stack_size < PTHREAD_STACK_MIN)
- stack_size = PTHREAD_STACK_MIN;
-#endif
+ min_stack_size = uv__min_stack_size();
+ if (stack_size < min_stack_size)
+ stack_size = min_stack_size;
}
if (stack_size > 0) {
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index 8cefc150b..44fdb9c18 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -62,10 +62,25 @@ static int isreallyatty(int file) {
#define isatty(fd) isreallyatty(fd)
#endif
+#if !defined(CMAKE_BOOTSTRAP)
+
static int orig_termios_fd = -1;
static struct termios orig_termios;
static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
+int uv__tcsetattr(int fd, int how, const struct termios *term) {
+ int rc;
+
+ do
+ rc = tcsetattr(fd, how, term);
+ while (rc == -1 && errno == EINTR);
+
+ if (rc == -1)
+ return UV__ERR(errno);
+
+ return 0;
+}
+
static int uv__tty_is_slave(const int fd) {
int result;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -265,13 +280,18 @@ static void uv__tty_make_raw(struct termios* tio) {
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
struct termios tmp;
int fd;
+ int rc;
if (tty->mode == (int) mode)
return 0;
fd = uv__stream_fd(tty);
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
- if (tcgetattr(fd, &tty->orig_termios))
+ do
+ rc = tcgetattr(fd, &tty->orig_termios);
+ while (rc == -1 && errno == EINTR);
+
+ if (rc == -1)
return UV__ERR(errno);
/* This is used for uv_tty_reset_mode() */
@@ -301,11 +321,11 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
/* Apply changes after draining */
- if (tcsetattr(fd, TCSADRAIN, &tmp))
- return UV__ERR(errno);
+ rc = uv__tcsetattr(fd, TCSADRAIN, &tmp);
+ if (rc == 0)
+ tty->mode = mode;
- tty->mode = mode;
- return 0;
+ return rc;
}
@@ -326,9 +346,10 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
return 0;
}
+#endif
uv_handle_type uv_guess_handle(uv_file file) {
- struct sockaddr sa;
+ struct sockaddr_storage ss;
struct stat s;
socklen_t len;
int type;
@@ -339,8 +360,24 @@ uv_handle_type uv_guess_handle(uv_file file) {
if (isatty(file))
return UV_TTY;
- if (fstat(file, &s))
+ if (fstat(file, &s)) {
+#if defined(__PASE__)
+ /* On ibmi receiving RST from TCP instead of FIN immediately puts fd into
+ * an error state. fstat will return EINVAL, getsockname will also return
+ * EINVAL, even if sockaddr_storage is valid. (If file does not refer to a
+ * socket, ENOTSOCK is returned instead.)
+ * In such cases, we will permit the user to open the connection as uv_tcp
+ * still, so that the user can get immediately notified of the error in
+ * their read callback and close this fd.
+ */
+ len = sizeof(ss);
+ if (getsockname(file, (struct sockaddr*) &ss, &len)) {
+ if (errno == EINVAL)
+ return UV_TCP;
+ }
+#endif
return UV_UNKNOWN_HANDLE;
+ }
if (S_ISREG(s.st_mode))
return UV_FILE;
@@ -354,16 +391,29 @@ uv_handle_type uv_guess_handle(uv_file file) {
if (!S_ISSOCK(s.st_mode))
return UV_UNKNOWN_HANDLE;
- len = sizeof(type);
- if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
+ len = sizeof(ss);
+ if (getsockname(file, (struct sockaddr*) &ss, &len)) {
+#if defined(_AIX)
+ /* On aix receiving RST from TCP instead of FIN immediately puts fd into
+ * an error state. In such case getsockname will return EINVAL, even if
+ * sockaddr_storage is valid.
+ * In such cases, we will permit the user to open the connection as uv_tcp
+ * still, so that the user can get immediately notified of the error in
+ * their read callback and close this fd.
+ */
+ if (errno == EINVAL) {
+ return UV_TCP;
+ }
+#endif
return UV_UNKNOWN_HANDLE;
+ }
- len = sizeof(sa);
- if (getsockname(file, &sa, &len))
+ len = sizeof(type);
+ if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
return UV_UNKNOWN_HANDLE;
if (type == SOCK_DGRAM)
- if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
+ if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)
return UV_UDP;
if (type == SOCK_STREAM) {
@@ -376,15 +426,16 @@ uv_handle_type uv_guess_handle(uv_file file) {
return UV_NAMED_PIPE;
#endif /* defined(_AIX) || defined(__DragonFly__) */
- if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
+ if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)
return UV_TCP;
- if (sa.sa_family == AF_UNIX)
+ if (ss.ss_family == AF_UNIX)
return UV_NAMED_PIPE;
}
return UV_UNKNOWN_HANDLE;
}
+#if !defined(CMAKE_BOOTSTRAP)
/* This function is async signal-safe, meaning that it's safe to call from
* inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s
@@ -400,8 +451,7 @@ int uv_tty_reset_mode(void) {
err = 0;
if (orig_termios_fd != -1)
- if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
- err = UV__ERR(errno);
+ err = uv__tcsetattr(orig_termios_fd, TCSANOW, &orig_termios);
uv_spinlock_unlock(&termios_spinlock);
errno = saved_errno;
@@ -415,3 +465,5 @@ void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) {
int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) {
return UV_ENOTSUP;
}
+
+#endif
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index aee8d6393..4d985b88b 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -201,6 +201,7 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
for (k = 0; k < chunks; ++k) {
iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE;
iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE;
+ memset(&msgs[k].msg_hdr, 0, sizeof(msgs[k].msg_hdr));
msgs[k].msg_hdr.msg_iov = iov + k;
msgs[k].msg_hdr.msg_iovlen = 1;
msgs[k].msg_hdr.msg_name = peers + k;
@@ -494,7 +495,7 @@ static int uv__set_reuse(int fd) {
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno);
}
-#elif defined(SO_REUSEPORT) && !defined(__linux__)
+#elif defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno);
#else
@@ -655,16 +656,16 @@ int uv__udp_connect(uv_udp_t* handle,
}
/* From https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
- * Any of uv supported UNIXs kernel should be standardized, but the kernel
+ * Any of uv supported UNIXs kernel should be standardized, but the kernel
* implementation logic not same, let's use pseudocode to explain the udp
* disconnect behaviors:
- *
+ *
* Predefined stubs for pseudocode:
* 1. sodisconnect: The function to perform the real udp disconnect
* 2. pru_connect: The function to perform the real udp connect
* 3. so: The kernel object match with socket fd
* 4. addr: The sockaddr parameter from user space
- *
+ *
* BSDs:
* if(sodisconnect(so) == 0) { // udp disconnect succeed
* if (addr->sa_len != so->addr->sa_len) return EINVAL;
@@ -694,16 +695,25 @@ int uv__udp_disconnect(uv_udp_t* handle) {
#endif
memset(&addr, 0, sizeof(addr));
-
+
#if defined(__MVS__)
addr.ss_family = AF_UNSPEC;
#else
addr.sa_family = AF_UNSPEC;
#endif
-
+
do {
errno = 0;
+#ifdef __PASE__
+ /* On IBMi a connectionless transport socket can be disconnected by
+ * either setting the addr parameter to NULL or setting the
+ * addr_length parameter to zero, and issuing another connect().
+ * https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/connec.htm
+ */
+ r = connect(handle->io_watcher.fd, (struct sockaddr*) NULL, 0);
+#else
r = connect(handle->io_watcher.fd, (struct sockaddr*) &addr, sizeof(addr));
+#endif
} while (r == -1 && errno == EINTR);
if (r == -1) {
@@ -927,7 +937,8 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
!defined(__NetBSD__) && \
!defined(__ANDROID__) && \
!defined(__DragonFly__) && \
- !defined(__QNX__)
+ !defined(__QNX__) && \
+ !defined(__GNU__)
static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,
const char* interface_addr,
@@ -1119,7 +1130,8 @@ int uv_udp_set_source_membership(uv_udp_t* handle,
!defined(__NetBSD__) && \
!defined(__ANDROID__) && \
!defined(__DragonFly__) && \
- !defined(__QNX__)
+ !defined(__QNX__) && \
+ !defined(__GNU__)
int err;
union uv__sockaddr mcast_addr;
union uv__sockaddr src_addr;
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index e88347a36..d8f7b0e48 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -296,7 +296,9 @@ int uv_tcp_bind(uv_tcp_t* handle,
if (handle->type != UV_TCP)
return UV_EINVAL;
-
+ if (uv__is_closing(handle)) {
+ return UV_EINVAL;
+ }
if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h
index 8a190bf8f..6001b0cf6 100644
--- a/Utilities/cmlibuv/src/uv-common.h
+++ b/Utilities/cmlibuv/src/uv-common.h
@@ -130,7 +130,10 @@ enum {
UV_SIGNAL_ONE_SHOT = 0x02000000,
/* Only used by uv_poll_t handles. */
- UV_HANDLE_POLL_SLOW = 0x01000000
+ UV_HANDLE_POLL_SLOW = 0x01000000,
+
+ /* Only used by uv_process_t handles. */
+ UV_HANDLE_REAP = 0x10000000
};
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c
index d787f6604..b904676e3 100644
--- a/Utilities/cmlibuv/src/win/async.c
+++ b/Utilities/cmlibuv/src/win/async.c
@@ -28,7 +28,7 @@
#include "req-inl.h"
-void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
+void uv__async_endgame(uv_loop_t* loop, uv_async_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING &&
!handle->async_sent) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
@@ -54,9 +54,9 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
}
-void uv_async_close(uv_loop_t* loop, uv_async_t* handle) {
+void uv__async_close(uv_loop_t* loop, uv_async_t* handle) {
if (!((uv_async_t*)handle)->async_sent) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
uv__handle_closing(handle);
@@ -83,7 +83,7 @@ int uv_async_send(uv_async_t* handle) {
}
-void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
+void uv__process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
uv_req_t* req) {
assert(handle->type == UV_ASYNC);
assert(req->type == UV_WAKEUP);
@@ -91,7 +91,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
handle->async_sent = 0;
if (handle->flags & UV_HANDLE_CLOSING) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
+ uv__want_endgame(loop, (uv_handle_t*)handle);
} else if (handle->async_cb != NULL) {
handle->async_cb(handle);
}
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index e53a0f8e2..67af93e65 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -84,10 +84,12 @@ static int uv__loops_capacity;
#define UV__LOOPS_CHUNK_SIZE 8
static uv_mutex_t uv__loops_lock;
+
static void uv__loops_init(void) {
uv_mutex_init(&uv__loops_lock);
}
+
static int uv__loops_add(uv_loop_t* loop) {
uv_loop_t** new_loops;
int new_capacity, i;
@@ -115,6 +117,7 @@ failed_loops_realloc:
return ERROR_OUTOFMEMORY;
}
+
static void uv__loops_remove(uv_loop_t* loop) {
int loop_index;
int smaller_capacity;
@@ -173,7 +176,7 @@ void uv__wake_all_loops(void) {
uv_mutex_unlock(&uv__loops_lock);
}
-static void uv_init(void) {
+static void uv__init(void) {
/* Tell Windows that we will handle critical errors. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
@@ -199,19 +202,19 @@ static void uv_init(void) {
/* Fetch winapi function pointers. This must be done first because other
* initialization code might need these function pointers to be loaded.
*/
- uv_winapi_init();
+ uv__winapi_init();
/* Initialize winsock */
- uv_winsock_init();
+ uv__winsock_init();
/* Initialize FS */
- uv_fs_init();
+ uv__fs_init();
/* Initialize signal stuff */
- uv_signals_init();
+ uv__signals_init();
/* Initialize console */
- uv_console_init();
+ uv__console_init();
/* Initialize utilities */
uv__util_init();
@@ -327,7 +330,7 @@ void uv_update_time(uv_loop_t* loop) {
void uv__once_init(void) {
- uv_once(&uv_init_guard_, uv_init);
+ uv_once(&uv_init_guard_, uv__init);
}
@@ -395,23 +398,28 @@ int uv_loop_fork(uv_loop_t* loop) {
}
-int uv_backend_timeout(const uv_loop_t* loop) {
- if (loop->stop_flag != 0)
- return 0;
-
- if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
- return 0;
+static int uv__loop_alive(const uv_loop_t* loop) {
+ return uv__has_active_handles(loop) ||
+ uv__has_active_reqs(loop) ||
+ loop->pending_reqs_tail != NULL ||
+ loop->endgame_handles != NULL;
+}
- if (loop->pending_reqs_tail)
- return 0;
- if (loop->endgame_handles)
- return 0;
+int uv_loop_alive(const uv_loop_t* loop) {
+ return uv__loop_alive(loop);
+}
- if (loop->idle_handles)
- return 0;
- return uv__next_timeout(loop);
+int uv_backend_timeout(const uv_loop_t* loop) {
+ if (loop->stop_flag == 0 &&
+ /* uv__loop_alive(loop) && */
+ (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
+ loop->pending_reqs_tail == NULL &&
+ loop->idle_handles == NULL &&
+ loop->endgame_handles == NULL)
+ return uv__next_timeout(loop);
+ return 0;
}
@@ -462,8 +470,8 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
if (overlapped) {
/* Package was dequeued */
- req = uv_overlapped_to_req(overlapped);
- uv_insert_pending_req(loop, req);
+ req = uv__overlapped_to_req(overlapped);
+ uv__insert_pending_req(loop, req);
/* Some time might have passed waiting for I/O,
* so update the loop time here.
@@ -547,8 +555,8 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
* meant only to wake us up.
*/
if (overlappeds[i].lpOverlapped) {
- req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
- uv_insert_pending_req(loop, req);
+ req = uv__overlapped_to_req(overlappeds[i].lpOverlapped);
+ uv__insert_pending_req(loop, req);
}
}
@@ -581,22 +589,10 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
}
-static int uv__loop_alive(const uv_loop_t* loop) {
- return uv__has_active_handles(loop) ||
- uv__has_active_reqs(loop) ||
- loop->endgame_handles != NULL;
-}
-
-
-int uv_loop_alive(const uv_loop_t* loop) {
- return uv__loop_alive(loop);
-}
-
-
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
- int ran_pending;
+ int can_sleep;
r = uv__loop_alive(loop);
if (!r)
@@ -606,12 +602,14 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
uv_update_time(loop);
uv__run_timers(loop);
- ran_pending = uv_process_reqs(loop);
- uv_idle_invoke(loop);
- uv_prepare_invoke(loop);
+ can_sleep = loop->pending_reqs_tail == NULL && loop->idle_handles == NULL;
+
+ uv__process_reqs(loop);
+ uv__idle_invoke(loop);
+ uv__prepare_invoke(loop);
timeout = 0;
- if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
+ if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
if (pGetQueuedCompletionStatusEx)
@@ -619,6 +617,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
else
uv__poll_wine(loop, timeout);
+ /* Process immediate callbacks (e.g. write_cb) a small fixed number of
+ * times to avoid loop starvation.*/
+ for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++)
+ uv__process_reqs(loop);
+
/* Run one final update on the provider_idle_time in case uv__poll*
* returned because the timeout expired, but no events were received. This
* call will be ignored if the provider_entry_time was either never set (if
@@ -626,8 +629,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
*/
uv__metrics_update_idle_time(loop);
- uv_check_invoke(loop);
- uv_process_endgames(loop);
+ uv__check_invoke(loop);
+ uv__process_endgames(loop);
if (mode == UV_RUN_ONCE) {
/* UV_RUN_ONCE implies forward progress: at least one callback must have
@@ -638,6 +641,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
+ uv_update_time(loop);
uv__run_timers(loop);
}
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 76da07755..6758c7c78 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -33,7 +33,7 @@
const unsigned int uv_directory_watcher_buffer_size = 4096;
-static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
+static void uv__fs_event_queue_readdirchanges(uv_loop_t* loop,
uv_fs_event_t* handle) {
assert(handle->dir_handle != INVALID_HANDLE_VALUE);
assert(!handle->req_pending);
@@ -57,15 +57,15 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
NULL)) {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(&handle->req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)&handle->req);
+ uv__insert_pending_req(loop, (uv_req_t*)&handle->req);
}
handle->req_pending = 1;
}
-static void uv_relative_path(const WCHAR* filename,
- const WCHAR* dir,
- WCHAR** relpath) {
+static void uv__relative_path(const WCHAR* filename,
+ const WCHAR* dir,
+ WCHAR** relpath) {
size_t relpathlen;
size_t filenamelen = wcslen(filename);
size_t dirlen = wcslen(dir);
@@ -80,7 +80,7 @@ static void uv_relative_path(const WCHAR* filename,
(*relpath)[relpathlen] = L'\0';
}
-static int uv_split_path(const WCHAR* filename, WCHAR** dir,
+static int uv__split_path(const WCHAR* filename, WCHAR** dir,
WCHAR** file) {
size_t len, i;
DWORD dir_len;
@@ -255,12 +255,12 @@ int uv_fs_event_start(uv_fs_event_t* handle,
short_path_done:
short_path = short_path_buffer;
- if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
+ if (uv__split_path(pathw, &dir, &handle->filew) != 0) {
last_error = GetLastError();
goto error;
}
- if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) {
+ if (uv__split_path(short_path, NULL, &handle->short_filew) != 0) {
last_error = GetLastError();
goto error;
}
@@ -423,7 +423,7 @@ static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) {
}
-void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
+void uv__process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fs_event_t* handle) {
FILE_NOTIFY_INFORMATION* file_info;
int err, sizew, size;
@@ -442,7 +442,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
*/
if (!uv__is_active(handle)) {
if (handle->flags & UV_HANDLE_CLOSING) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
return;
}
@@ -515,9 +515,9 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (long_filenamew) {
/* Get the file name out of the long path. */
- uv_relative_path(long_filenamew,
- handle->dirw,
- &filenamew);
+ uv__relative_path(long_filenamew,
+ handle->dirw,
+ &filenamew);
uv__free(long_filenamew);
long_filenamew = filenamew;
sizew = -1;
@@ -575,26 +575,26 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
}
if (handle->flags & UV_HANDLE_CLOSING) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
+ uv__want_endgame(loop, (uv_handle_t*)handle);
} else if (uv__is_active(handle)) {
- uv_fs_event_queue_readdirchanges(loop, handle);
+ uv__fs_event_queue_readdirchanges(loop, handle);
}
}
-void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
+void uv__fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
uv_fs_event_stop(handle);
uv__handle_closing(handle);
if (!handle->req_pending) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
+ uv__want_endgame(loop, (uv_handle_t*)handle);
}
}
-void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
+void uv__fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 903764144..792307995 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -46,7 +46,7 @@
do { \
if (req == NULL) \
return UV_EINVAL; \
- uv_fs_req_init(loop, req, subtype, cb); \
+ uv__fs_req_init(loop, req, subtype, cb); \
} \
while (0)
@@ -132,7 +132,7 @@ static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGE
static DWORD uv__allocation_granularity;
-void uv_fs_init(void) {
+void uv__fs_init(void) {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
@@ -241,7 +241,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
-INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
+INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
uv_fs_type fs_type, const uv_fs_cb cb) {
uv__once_init();
UV_REQ_INIT(req, UV_FS);
@@ -912,12 +912,11 @@ void fs__read(uv_fs_t* req) {
SET_REQ_RESULT(req, bytes);
} else {
error = GetLastError();
-
if (error == ERROR_ACCESS_DENIED) {
error = ERROR_INVALID_FLAGS;
}
- if (error == ERROR_HANDLE_EOF) {
+ if (error == ERROR_HANDLE_EOF || error == ERROR_BROKEN_PIPE) {
SET_REQ_RESULT(req, bytes);
} else {
SET_REQ_WIN32_ERROR(req, error);
@@ -1881,8 +1880,9 @@ INLINE static DWORD fs__stat_impl_from_path(WCHAR* path,
NULL);
if (handle == INVALID_HANDLE_VALUE)
- ret = GetLastError();
- else if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
+ return GetLastError();
+
+ if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
ret = GetLastError();
else
ret = 0;
@@ -2300,13 +2300,13 @@ INLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
flags,
NULL);
- if (handle == INVALID_HANDLE_VALUE) {
- ret = GetLastError();
- } else if (fs__utime_handle(handle, atime, mtime) != 0) {
+ if (handle == INVALID_HANDLE_VALUE)
+ return GetLastError();
+
+ if (fs__utime_handle(handle, atime, mtime) != 0)
ret = GetLastError();
- } else {
+ else
ret = 0;
- }
CloseHandle(handle);
return ret;
diff --git a/Utilities/cmlibuv/src/win/handle-inl.h b/Utilities/cmlibuv/src/win/handle-inl.h
index 82c657d57..5c843c241 100644
--- a/Utilities/cmlibuv/src/win/handle-inl.h
+++ b/Utilities/cmlibuv/src/win/handle-inl.h
@@ -55,7 +55,7 @@
\
if (handle->flags & UV_HANDLE_CLOSING && \
handle->reqs_pending == 0) { \
- uv_want_endgame(loop, (uv_handle_t*)handle); \
+ uv__want_endgame(loop, (uv_handle_t*)handle); \
} \
} while (0)
@@ -85,7 +85,7 @@
} while (0)
-INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
+INLINE static void uv__want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {
handle->flags |= UV_HANDLE_ENDGAME_QUEUED;
@@ -95,7 +95,7 @@ INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
}
-INLINE static void uv_process_endgames(uv_loop_t* loop) {
+INLINE static void uv__process_endgames(uv_loop_t* loop) {
uv_handle_t* handle;
while (loop->endgame_handles) {
@@ -106,23 +106,23 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
switch (handle->type) {
case UV_TCP:
- uv_tcp_endgame(loop, (uv_tcp_t*) handle);
+ uv__tcp_endgame(loop, (uv_tcp_t*) handle);
break;
case UV_NAMED_PIPE:
- uv_pipe_endgame(loop, (uv_pipe_t*) handle);
+ uv__pipe_endgame(loop, (uv_pipe_t*) handle);
break;
case UV_TTY:
- uv_tty_endgame(loop, (uv_tty_t*) handle);
+ uv__tty_endgame(loop, (uv_tty_t*) handle);
break;
case UV_UDP:
- uv_udp_endgame(loop, (uv_udp_t*) handle);
+ uv__udp_endgame(loop, (uv_udp_t*) handle);
break;
case UV_POLL:
- uv_poll_endgame(loop, (uv_poll_t*) handle);
+ uv__poll_endgame(loop, (uv_poll_t*) handle);
break;
case UV_TIMER:
@@ -133,23 +133,23 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
case UV_PREPARE:
case UV_CHECK:
case UV_IDLE:
- uv_loop_watcher_endgame(loop, handle);
+ uv__loop_watcher_endgame(loop, handle);
break;
case UV_ASYNC:
- uv_async_endgame(loop, (uv_async_t*) handle);
+ uv__async_endgame(loop, (uv_async_t*) handle);
break;
case UV_SIGNAL:
- uv_signal_endgame(loop, (uv_signal_t*) handle);
+ uv__signal_endgame(loop, (uv_signal_t*) handle);
break;
case UV_PROCESS:
- uv_process_endgame(loop, (uv_process_t*) handle);
+ uv__process_endgame(loop, (uv_process_t*) handle);
break;
case UV_FS_EVENT:
- uv_fs_event_endgame(loop, (uv_fs_event_t*) handle);
+ uv__fs_event_endgame(loop, (uv_fs_event_t*) handle);
break;
case UV_FS_POLL:
diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c
index 61e4df61b..53a81fdbc 100644
--- a/Utilities/cmlibuv/src/win/handle.c
+++ b/Utilities/cmlibuv/src/win/handle.c
@@ -77,63 +77,63 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
/* Handle-specific close actions */
switch (handle->type) {
case UV_TCP:
- uv_tcp_close(loop, (uv_tcp_t*)handle);
+ uv__tcp_close(loop, (uv_tcp_t*)handle);
return;
case UV_NAMED_PIPE:
- uv_pipe_close(loop, (uv_pipe_t*) handle);
+ uv__pipe_close(loop, (uv_pipe_t*) handle);
return;
case UV_TTY:
- uv_tty_close((uv_tty_t*) handle);
+ uv__tty_close((uv_tty_t*) handle);
return;
case UV_UDP:
- uv_udp_close(loop, (uv_udp_t*) handle);
+ uv__udp_close(loop, (uv_udp_t*) handle);
return;
case UV_POLL:
- uv_poll_close(loop, (uv_poll_t*) handle);
+ uv__poll_close(loop, (uv_poll_t*) handle);
return;
case UV_TIMER:
uv_timer_stop((uv_timer_t*)handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
+ uv__want_endgame(loop, handle);
return;
case UV_PREPARE:
uv_prepare_stop((uv_prepare_t*)handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
+ uv__want_endgame(loop, handle);
return;
case UV_CHECK:
uv_check_stop((uv_check_t*)handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
+ uv__want_endgame(loop, handle);
return;
case UV_IDLE:
uv_idle_stop((uv_idle_t*)handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
+ uv__want_endgame(loop, handle);
return;
case UV_ASYNC:
- uv_async_close(loop, (uv_async_t*) handle);
+ uv__async_close(loop, (uv_async_t*) handle);
return;
case UV_SIGNAL:
- uv_signal_close(loop, (uv_signal_t*) handle);
+ uv__signal_close(loop, (uv_signal_t*) handle);
return;
case UV_PROCESS:
- uv_process_close(loop, (uv_process_t*) handle);
+ uv__process_close(loop, (uv_process_t*) handle);
return;
case UV_FS_EVENT:
- uv_fs_event_close(loop, (uv_fs_event_t*) handle);
+ uv__fs_event_close(loop, (uv_fs_event_t*) handle);
return;
case UV_FS_POLL:
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 7e1aef444..3e92a66a0 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -76,25 +76,28 @@ typedef struct {
uint32_t delayed_error;
} uv__ipc_socket_xfer_info_t;
-int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
-int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
-int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
+int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
+int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
+int uv__tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
-int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
+int uv__tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[],
unsigned int nbufs);
-void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);
-void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);
+void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_write_t* req);
-void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_req_t* req);
-void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_connect_t* req);
+void uv__process_tcp_shutdown_req(uv_loop_t* loop,
+ uv_tcp_t* stream,
+ uv_shutdown_t* req);
-void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
-void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
+void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
+void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
int uv__tcp_xfer_export(uv_tcp_t* handle,
int pid,
@@ -108,12 +111,12 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp,
/*
* UDP
*/
-void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
-void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
+void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
+void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
uv_udp_send_t* req);
-void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle);
-void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
+void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle);
+void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
/*
@@ -122,9 +125,9 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
int uv__create_stdio_pipe_pair(uv_loop_t* loop,
uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags);
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
-int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
-int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
+int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
+int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client);
+int uv__pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
void uv__pipe_read_stop(uv_pipe_t* handle);
int uv__pipe_write(uv_loop_t* loop,
@@ -134,75 +137,77 @@ int uv__pipe_write(uv_loop_t* loop,
size_t nbufs,
uv_stream_t* send_handle,
uv_write_cb cb);
+void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t* req);
-void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* req);
-void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_write_t* req);
-void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* raw_req);
-void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_connect_t* req);
-void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_shutdown_t* req);
-void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
-void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);
-void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
+void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
+void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
/*
* TTY
*/
-void uv_console_init(void);
+void uv__console_init(void);
-int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
+int uv__tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
-int uv_tty_read_stop(uv_tty_t* handle);
-int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
+int uv__tty_read_stop(uv_tty_t* handle);
+int uv__tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[],
unsigned int nbufs);
-void uv_tty_close(uv_tty_t* handle);
+void uv__tty_close(uv_tty_t* handle);
-void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* req);
-void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req);
/*
- * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
* TODO: find a way to remove it
*/
-void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req);
/*
- * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
* TODO: find a way to remove it
*/
-void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req);
-
-void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
+void uv__process_tty_shutdown_req(uv_loop_t* loop,
+ uv_tty_t* stream,
+ uv_shutdown_t* req);
+void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
/*
* Poll watchers
*/
-void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
+void uv__process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
uv_req_t* req);
-int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
-void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
+int uv__poll_close(uv_loop_t* loop, uv_poll_t* handle);
+void uv__poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
/*
* Loop watchers
*/
-void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
+void uv__loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
-void uv_prepare_invoke(uv_loop_t* loop);
-void uv_check_invoke(uv_loop_t* loop);
-void uv_idle_invoke(uv_loop_t* loop);
+void uv__prepare_invoke(uv_loop_t* loop);
+void uv__check_invoke(uv_loop_t* loop);
+void uv__idle_invoke(uv_loop_t* loop);
void uv__once_init(void);
@@ -210,53 +215,47 @@ void uv__once_init(void);
/*
* Async watcher
*/
-void uv_async_close(uv_loop_t* loop, uv_async_t* handle);
-void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle);
+void uv__async_close(uv_loop_t* loop, uv_async_t* handle);
+void uv__async_endgame(uv_loop_t* loop, uv_async_t* handle);
-void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
+void uv__process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
uv_req_t* req);
/*
* Signal watcher
*/
-void uv_signals_init(void);
+void uv__signals_init(void);
int uv__signal_dispatch(int signum);
-void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);
-void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle);
+void uv__signal_close(uv_loop_t* loop, uv_signal_t* handle);
+void uv__signal_endgame(uv_loop_t* loop, uv_signal_t* handle);
-void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
+void uv__process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
uv_req_t* req);
/*
* Spawn
*/
-void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle);
-void uv_process_close(uv_loop_t* loop, uv_process_t* handle);
-void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle);
-
-
-/*
- * Error
- */
-int uv_translate_sys_error(int sys_errno);
+void uv__process_proc_exit(uv_loop_t* loop, uv_process_t* handle);
+void uv__process_close(uv_loop_t* loop, uv_process_t* handle);
+void uv__process_endgame(uv_loop_t* loop, uv_process_t* handle);
/*
* FS
*/
-void uv_fs_init(void);
+void uv__fs_init(void);
/*
* FS Event
*/
-void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
+void uv__process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fs_event_t* handle);
-void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);
-void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
+void uv__fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);
+void uv__fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
/*
@@ -303,28 +302,28 @@ HANDLE uv__stdio_handle(BYTE* buffer, int fd);
/*
* Winapi and ntapi utility functions
*/
-void uv_winapi_init(void);
+void uv__winapi_init(void);
/*
* Winsock utility functions
*/
-void uv_winsock_init(void);
+void uv__winsock_init(void);
-int uv_ntstatus_to_winsock_error(NTSTATUS status);
+int uv__ntstatus_to_winsock_error(NTSTATUS status);
-BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target);
-BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target);
+BOOL uv__get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target);
+BOOL uv__get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target);
-int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
+int WSAAPI uv__wsarecv_workaround(SOCKET socket, WSABUF* buffers,
DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
+int WSAAPI uv__wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
int* addr_len, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+int WSAAPI uv__msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);
/* Whether there are any non-IFS LSPs stacked on TCP */
diff --git a/Utilities/cmlibuv/src/win/loop-watcher.c b/Utilities/cmlibuv/src/win/loop-watcher.c
index ad7fbea16..fad9e8a8e 100644
--- a/Utilities/cmlibuv/src/win/loop-watcher.c
+++ b/Utilities/cmlibuv/src/win/loop-watcher.c
@@ -26,7 +26,7 @@
#include "handle-inl.h"
-void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
+void uv__loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
@@ -104,7 +104,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
} \
\
\
- void uv_##name##_invoke(uv_loop_t* loop) { \
+ void uv__##name##_invoke(uv_loop_t* loop) { \
uv_##name##_t* handle; \
\
(loop)->next_##name##_handle = (loop)->name##_handles; \
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index 984b766bb..998461811 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -98,13 +98,13 @@ static void eof_timer_destroy(uv_pipe_t* pipe);
static void eof_timer_close_cb(uv_handle_t* handle);
-static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
+static void uv__unique_pipe_name(char* ptr, char* name, size_t size) {
snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId());
}
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
- uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
+ uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
handle->reqs_pending = 0;
handle->handle = INVALID_HANDLE_VALUE;
@@ -120,15 +120,11 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
}
-static void uv_pipe_connection_init(uv_pipe_t* handle) {
- uv_connection_init((uv_stream_t*) handle);
+static void uv__pipe_connection_init(uv_pipe_t* handle) {
+ assert(!(handle->flags & UV_HANDLE_PIPESERVER));
+ uv__connection_init((uv_stream_t*) handle);
handle->read_req.data = handle;
handle->pipe.conn.eof_timer = NULL;
- assert(!(handle->flags & UV_HANDLE_PIPESERVER));
- if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
- handle->pipe.conn.readfile_thread_handle = NULL;
- InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
- }
}
@@ -209,7 +205,7 @@ static int uv__pipe_server(
int err;
for (;;) {
- uv_unique_pipe_name(random, name, nameSize);
+ uv__unique_pipe_name(random, name, nameSize);
pipeHandle = CreateNamedPipeA(name,
access | FILE_FLAG_FIRST_PIPE_INSTANCE,
@@ -393,6 +389,8 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop,
unsigned int client_flags;
int err;
+ uv__pipe_connection_init(parent_pipe);
+
server_pipe = INVALID_HANDLE_VALUE;
client_pipe = INVALID_HANDLE_VALUE;
@@ -427,7 +425,6 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop,
goto error;
}
- uv_pipe_connection_init(parent_pipe);
parent_pipe->handle = server_pipe;
*child_pipe_ptr = client_pipe;
@@ -450,11 +447,11 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop,
}
-static int uv_set_pipe_handle(uv_loop_t* loop,
- uv_pipe_t* handle,
- HANDLE pipeHandle,
- int fd,
- DWORD duplex_flags) {
+static int uv__set_pipe_handle(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ HANDLE pipeHandle,
+ int fd,
+ DWORD duplex_flags) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_MODE_INFORMATION mode_info;
@@ -462,7 +459,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
DWORD current_mode = 0;
DWORD err = 0;
- if (handle->flags & UV_HANDLE_PIPESERVER)
+ assert(handle->flags & UV_HANDLE_CONNECTION);
+ assert(!(handle->flags & UV_HANDLE_PIPESERVER));
+ if (handle->flags & UV_HANDLE_CLOSING)
return UV_EINVAL;
if (handle->handle != INVALID_HANDLE_VALUE)
return UV_EBUSY;
@@ -478,18 +477,17 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
*/
if (!GetNamedPipeHandleState(pipeHandle, &current_mode, NULL, NULL,
NULL, NULL, 0)) {
- return -1;
+ return uv_translate_sys_error(GetLastError());
} else if (current_mode & PIPE_NOWAIT) {
- SetLastError(ERROR_ACCESS_DENIED);
- return -1;
+ return UV_EACCES;
}
} else {
/* If this returns ERROR_INVALID_PARAMETER we probably opened
* something that is not a pipe. */
if (err == ERROR_INVALID_PARAMETER) {
- SetLastError(WSAENOTSOCK);
+ return UV_ENOTSOCK;
}
- return -1;
+ return uv_translate_sys_error(err);
}
}
@@ -500,13 +498,15 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
sizeof(mode_info),
FileModeInformation);
if (nt_status != STATUS_SUCCESS) {
- return -1;
+ return uv_translate_sys_error(err);
}
if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||
mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {
/* Non-overlapped pipe. */
handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE;
+ handle->pipe.conn.readfile_thread_handle = NULL;
+ InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
} else {
/* Overlapped pipe. Try to associate with IOCP. */
if (CreateIoCompletionPort(pipeHandle,
@@ -578,135 +578,109 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
}
-void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
- int err;
+void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t *req) {
DWORD result;
- uv_shutdown_t* req;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_PIPE_LOCAL_INFORMATION pipe_info;
- uv__ipc_xfer_queue_item_t* xfer_queue_item;
-
- if ((handle->flags & UV_HANDLE_CONNECTION) &&
- handle->stream.conn.shutdown_req != NULL &&
- handle->stream.conn.write_reqs_pending == 0) {
- req = handle->stream.conn.shutdown_req;
-
- /* Clear the shutdown_req field so we don't go here again. */
- handle->stream.conn.shutdown_req = NULL;
-
- if (handle->flags & UV_HANDLE_CLOSING) {
- UNREGISTER_HANDLE_REQ(loop, handle, req);
-
- /* Already closing. Cancel the shutdown. */
- if (req->cb) {
- req->cb(req, UV_ECANCELED);
- }
-
- DECREASE_PENDING_REQ_COUNT(handle);
- return;
- }
- /* Try to avoid flushing the pipe buffer in the thread pool. */
- nt_status = pNtQueryInformationFile(handle->handle,
- &io_status,
- &pipe_info,
- sizeof pipe_info,
- FilePipeLocalInformation);
-
- if (nt_status != STATUS_SUCCESS) {
- /* Failure */
- UNREGISTER_HANDLE_REQ(loop, handle, req);
-
- handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
- if (req->cb) {
- err = pRtlNtStatusToDosError(nt_status);
- req->cb(req, uv_translate_sys_error(err));
- }
-
- DECREASE_PENDING_REQ_COUNT(handle);
- return;
- }
+ assert(handle->flags & UV_HANDLE_CONNECTION);
+ assert(req != NULL);
+ assert(handle->stream.conn.write_reqs_pending == 0);
+ SET_REQ_SUCCESS(req);
- if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
- /* Short-circuit, no need to call FlushFileBuffers. */
- uv_insert_pending_req(loop, (uv_req_t*) req);
- return;
- }
+ if (handle->flags & UV_HANDLE_CLOSING) {
+ uv__insert_pending_req(loop, (uv_req_t*) req);
+ return;
+ }
- /* Run FlushFileBuffers in the thread pool. */
- result = QueueUserWorkItem(pipe_shutdown_thread_proc,
- req,
- WT_EXECUTELONGFUNCTION);
- if (result) {
- return;
+ /* Try to avoid flushing the pipe buffer in the thread pool. */
+ nt_status = pNtQueryInformationFile(handle->handle,
+ &io_status,
+ &pipe_info,
+ sizeof pipe_info,
+ FilePipeLocalInformation);
- } else {
- /* Failure. */
- UNREGISTER_HANDLE_REQ(loop, handle, req);
+ if (nt_status != STATUS_SUCCESS) {
+ SET_REQ_ERROR(req, pRtlNtStatusToDosError(nt_status));
+ handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */
+ uv__insert_pending_req(loop, (uv_req_t*) req);
+ return;
+ }
- handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
- if (req->cb) {
- err = GetLastError();
- req->cb(req, uv_translate_sys_error(err));
- }
+ if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
+ /* Short-circuit, no need to call FlushFileBuffers:
+ * all writes have been read. */
+ uv__insert_pending_req(loop, (uv_req_t*) req);
+ return;
+ }
- DECREASE_PENDING_REQ_COUNT(handle);
- return;
- }
+ /* Run FlushFileBuffers in the thread pool. */
+ result = QueueUserWorkItem(pipe_shutdown_thread_proc,
+ req,
+ WT_EXECUTELONGFUNCTION);
+ if (!result) {
+ SET_REQ_ERROR(req, GetLastError());
+ handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */
+ uv__insert_pending_req(loop, (uv_req_t*) req);
+ return;
}
+}
- if (handle->flags & UV_HANDLE_CLOSING &&
- handle->reqs_pending == 0) {
- assert(!(handle->flags & UV_HANDLE_CLOSED));
- if (handle->flags & UV_HANDLE_CONNECTION) {
- /* Free pending sockets */
- while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
- QUEUE* q;
- SOCKET socket;
+void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
+ uv__ipc_xfer_queue_item_t* xfer_queue_item;
- q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
- QUEUE_REMOVE(q);
- xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
+ assert(handle->reqs_pending == 0);
+ assert(handle->flags & UV_HANDLE_CLOSING);
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
- /* Materialize socket and close it */
- socket = WSASocketW(FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- &xfer_queue_item->xfer_info.socket_info,
- 0,
- WSA_FLAG_OVERLAPPED);
- uv__free(xfer_queue_item);
+ if (handle->flags & UV_HANDLE_CONNECTION) {
+ /* Free pending sockets */
+ while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
+ QUEUE* q;
+ SOCKET socket;
+
+ q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
+ QUEUE_REMOVE(q);
+ xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
+
+ /* Materialize socket and close it */
+ socket = WSASocketW(FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ &xfer_queue_item->xfer_info.socket_info,
+ 0,
+ WSA_FLAG_OVERLAPPED);
+ uv__free(xfer_queue_item);
+
+ if (socket != INVALID_SOCKET)
+ closesocket(socket);
+ }
+ handle->pipe.conn.ipc_xfer_queue_length = 0;
- if (socket != INVALID_SOCKET)
- closesocket(socket);
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
+ if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
+ UnregisterWait(handle->read_req.wait_handle);
+ handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
}
- handle->pipe.conn.ipc_xfer_queue_length = 0;
-
- if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
- UnregisterWait(handle->read_req.wait_handle);
- handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
- }
- if (handle->read_req.event_handle != NULL) {
- CloseHandle(handle->read_req.event_handle);
- handle->read_req.event_handle = NULL;
- }
+ if (handle->read_req.event_handle != NULL) {
+ CloseHandle(handle->read_req.event_handle);
+ handle->read_req.event_handle = NULL;
}
-
- if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
- DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
- if (handle->flags & UV_HANDLE_PIPESERVER) {
- assert(handle->pipe.serv.accept_reqs);
- uv__free(handle->pipe.serv.accept_reqs);
- handle->pipe.serv.accept_reqs = NULL;
- }
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
+ DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
+ }
- uv__handle_close(handle);
+ if (handle->flags & UV_HANDLE_PIPESERVER) {
+ assert(handle->pipe.serv.accept_reqs);
+ uv__free(handle->pipe.serv.accept_reqs);
+ handle->pipe.serv.accept_reqs = NULL;
}
+
+ uv__handle_close(handle);
}
@@ -731,7 +705,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
if (!name) {
return UV_EINVAL;
}
-
+ if (uv__is_closing(handle)) {
+ return UV_EINVAL;
+ }
if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
handle->pipe.serv.pending_instances = default_pending_pipe_instances;
}
@@ -815,7 +791,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
assert(loop);
/* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
- * for the pipe to become available with WaitNamedPipe. */
+ * up to 30 seconds for the pipe to become available with WaitNamedPipe. */
while (WaitNamedPipeW(handle->name, 30000)) {
/* The pipe is now available, try to connect. */
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
@@ -825,9 +801,10 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
SwitchToThread();
}
- if (pipeHandle != INVALID_HANDLE_VALUE &&
- !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
SET_REQ_SUCCESS(req);
+ req->u.connect.pipeHandle = pipeHandle;
+ req->u.connect.duplex_flags = duplex_flags;
} else {
SET_REQ_ERROR(req, GetLastError());
}
@@ -849,6 +826,18 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
UV_REQ_INIT(req, UV_CONNECT);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
+ req->u.connect.pipeHandle = INVALID_HANDLE_VALUE;
+ req->u.connect.duplex_flags = 0;
+
+ if (handle->flags & UV_HANDLE_PIPESERVER) {
+ err = ERROR_INVALID_PARAMETER;
+ goto error;
+ }
+ if (handle->flags & UV_HANDLE_CONNECTION) {
+ err = ERROR_PIPE_BUSY;
+ goto error;
+ }
+ uv__pipe_connection_init(handle);
/* Convert name to UTF16. */
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
@@ -888,19 +877,10 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
goto error;
}
- assert(pipeHandle != INVALID_HANDLE_VALUE);
-
- if (uv_set_pipe_handle(loop,
- (uv_pipe_t*) req->handle,
- pipeHandle,
- -1,
- duplex_flags)) {
- err = GetLastError();
- goto error;
- }
-
+ req->u.connect.pipeHandle = pipeHandle;
+ req->u.connect.duplex_flags = duplex_flags;
SET_REQ_SUCCESS(req);
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
return;
@@ -916,7 +896,7 @@ error:
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, err);
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
return;
@@ -937,7 +917,7 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) {
/* Cancel asynchronous read. */
r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
assert(r || GetLastError() == ERROR_NOT_FOUND);
-
+ (void) r;
} else {
/* Cancel synchronous read (which is happening in the thread pool). */
HANDLE thread;
@@ -973,17 +953,30 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) {
void uv__pipe_read_stop(uv_pipe_t* handle) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
-
uv__pipe_interrupt_read(handle);
}
/* Cleans up uv_pipe_t (server or connection) and all resources associated with
* it. */
-void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
+void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
int i;
HANDLE pipeHandle;
+ if (handle->flags & UV_HANDLE_READING) {
+ handle->flags &= ~UV_HANDLE_READING;
+ DECREASE_ACTIVE_COUNT(loop, handle);
+ }
+
+ if (handle->flags & UV_HANDLE_LISTENING) {
+ handle->flags &= ~UV_HANDLE_LISTENING;
+ DECREASE_ACTIVE_COUNT(loop, handle);
+ }
+
+ handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
+
+ uv__handle_closing(handle);
+
uv__pipe_interrupt_read(handle);
if (handle->name) {
@@ -1003,45 +996,27 @@ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
}
if (handle->flags & UV_HANDLE_CONNECTION) {
- handle->flags &= ~UV_HANDLE_WRITABLE;
eof_timer_destroy(handle);
}
if ((handle->flags & UV_HANDLE_CONNECTION)
- && handle->handle != INVALID_HANDLE_VALUE)
+ && handle->handle != INVALID_HANDLE_VALUE) {
+ /* This will eventually destroy the write queue for us too. */
close_pipe(handle);
-}
-
-
-void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
- if (handle->flags & UV_HANDLE_READING) {
- handle->flags &= ~UV_HANDLE_READING;
- DECREASE_ACTIVE_COUNT(loop, handle);
- }
-
- if (handle->flags & UV_HANDLE_LISTENING) {
- handle->flags &= ~UV_HANDLE_LISTENING;
- DECREASE_ACTIVE_COUNT(loop, handle);
}
- uv_pipe_cleanup(loop, handle);
-
- if (handle->reqs_pending == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
- }
-
- handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
- uv__handle_closing(handle);
+ if (handle->reqs_pending == 0)
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
-static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
+static void uv__pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
uv_pipe_accept_t* req, BOOL firstInstance) {
assert(handle->flags & UV_HANDLE_LISTENING);
if (!firstInstance && !pipe_alloc_accept(loop, handle, req, FALSE)) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
return;
}
@@ -1061,7 +1036,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, GetLastError());
}
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
return;
}
@@ -1071,7 +1046,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
}
-int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
+int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
uv_loop_t* loop = server->loop;
uv_pipe_t* pipe_client;
uv_pipe_accept_t* req;
@@ -1099,6 +1074,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
} else {
pipe_client = (uv_pipe_t*) client;
+ uv__pipe_connection_init(pipe_client);
/* Find a connection instance that has been connected, but not yet
* accepted. */
@@ -1110,7 +1086,6 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
}
/* Initialize the client handle and copy the pipeHandle to the client */
- uv_pipe_connection_init(pipe_client);
pipe_client->handle = req->pipeHandle;
pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
@@ -1121,7 +1096,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
server->handle = INVALID_HANDLE_VALUE;
if (!(server->flags & UV_HANDLE_CLOSING)) {
- uv_pipe_queue_accept(loop, server, req, FALSE);
+ uv__pipe_queue_accept(loop, server, req, FALSE);
}
}
@@ -1130,7 +1105,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
/* Starts listening for connections for the given pipe. */
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
+int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
uv_loop_t* loop = handle->loop;
int i;
@@ -1162,7 +1137,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
- uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0);
+ uv__pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0);
}
return 0;
@@ -1306,7 +1281,7 @@ static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out
}
-static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
+static void uv__pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
uv_read_t* req;
int result;
@@ -1365,15 +1340,15 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
return;
error:
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
}
-int uv_pipe_read_start(uv_pipe_t* handle,
- uv_alloc_cb alloc_cb,
- uv_read_cb read_cb) {
+int uv__pipe_read_start(uv_pipe_t* handle,
+ uv_alloc_cb alloc_cb,
+ uv_read_cb read_cb) {
uv_loop_t* loop = handle->loop;
handle->flags |= UV_HANDLE_READING;
@@ -1391,14 +1366,14 @@ int uv_pipe_read_start(uv_pipe_t* handle,
uv_fatal_error(GetLastError(), "CreateEvent");
}
}
- uv_pipe_queue_read(loop, handle);
+ uv__pipe_queue_read(loop, handle);
}
return 0;
}
-static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle,
+static void uv__insert_non_overlapped_write_req(uv_pipe_t* handle,
uv_write_t* req) {
req->next_req = NULL;
if (handle->pipe.conn.non_overlapped_writes_tail) {
@@ -1434,7 +1409,7 @@ static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) {
}
-static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {
+static void uv__queue_non_overlapped_write(uv_pipe_t* handle) {
uv_write_t* req = uv_remove_non_overlapped_write_req(handle);
if (req) {
if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc,
@@ -1575,9 +1550,9 @@ static int uv__pipe_write_data(uv_loop_t* loop,
return 0;
} else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
req->write_buffer = write_buf;
- uv_insert_non_overlapped_write_req(handle, req);
+ uv__insert_non_overlapped_write_req(handle, req);
if (handle->stream.conn.write_reqs_pending == 0) {
- uv_queue_non_overlapped_write(handle);
+ uv__queue_non_overlapped_write(handle);
}
/* Request queued by the kernel. */
@@ -1790,7 +1765,7 @@ int uv__pipe_write(uv_loop_t* loop,
}
-static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
+static void uv__pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
uv_buf_t buf) {
/* If there is an eof timer running, we don't need it any more, so discard
* it. */
@@ -1802,7 +1777,7 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
}
-static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
+static void uv__pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
uv_buf_t buf) {
/* If there is an eof timer running, we don't need it any more, so discard
* it. */
@@ -1814,12 +1789,12 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
}
-static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
+static void uv__pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
int error, uv_buf_t buf) {
if (error == ERROR_BROKEN_PIPE) {
- uv_pipe_read_eof(loop, handle, buf);
+ uv__pipe_read_eof(loop, handle, buf);
} else {
- uv_pipe_read_error(loop, handle, error, buf);
+ uv__pipe_read_error(loop, handle, error, buf);
}
}
@@ -1890,7 +1865,7 @@ static DWORD uv__pipe_read_data(uv_loop_t* loop,
/* Read into the user buffer. */
if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
+ uv__pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
return 0; /* Break out of read loop. */
}
@@ -1977,14 +1952,14 @@ invalid:
err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
error:
- uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
+ uv__pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
return 0; /* Break out of read loop. */
}
-void uv_process_pipe_read_req(uv_loop_t* loop,
- uv_pipe_t* handle,
- uv_req_t* req) {
+void uv__process_pipe_read_req(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ uv_req_t* req) {
assert(handle->type == UV_NAMED_PIPE);
handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING);
@@ -2005,7 +1980,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop,
* indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to
* the user; we'll start a new zero-read at the end of this function. */
if (err != ERROR_OPERATION_ABORTED)
- uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
+ uv__pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
} else {
/* The zero-read completed without error, indicating there is data
@@ -2015,7 +1990,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop,
/* Get the number of bytes available. */
avail = 0;
if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
+ uv__pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
/* Read until we've either read all the bytes available, or the 'reading'
* flag is cleared. */
@@ -2044,12 +2019,12 @@ void uv_process_pipe_read_req(uv_loop_t* loop,
/* Start another zero-read request if necessary. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_pipe_queue_read(loop, handle);
+ uv__pipe_queue_read(loop, handle);
}
}
-void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_write_t* req) {
int err;
@@ -2091,26 +2066,25 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE &&
handle->pipe.conn.non_overlapped_writes_tail) {
assert(handle->stream.conn.write_reqs_pending > 0);
- uv_queue_non_overlapped_write(handle);
+ uv__queue_non_overlapped_write(handle);
}
- if (handle->stream.conn.shutdown_req != NULL &&
- handle->stream.conn.write_reqs_pending == 0) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
- }
+ if (handle->stream.conn.write_reqs_pending == 0)
+ if (handle->flags & UV_HANDLE_SHUTTING)
+ uv__pipe_shutdown(loop, handle, handle->stream.conn.shutdown_req);
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* raw_req) {
uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req;
assert(handle->type == UV_NAMED_PIPE);
if (handle->flags & UV_HANDLE_CLOSING) {
- /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
+ /* The req->pipeHandle should be freed already in uv__pipe_close(). */
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
DECREASE_PENDING_REQ_COUNT(handle);
return;
@@ -2130,7 +2104,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
req->pipeHandle = INVALID_HANDLE_VALUE;
}
if (!(handle->flags & UV_HANDLE_CLOSING)) {
- uv_pipe_queue_accept(loop, handle, req, FALSE);
+ uv__pipe_queue_accept(loop, handle, req, FALSE);
}
}
@@ -2138,54 +2112,74 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
}
-void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
+void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_connect_t* req) {
+ HANDLE pipeHandle;
+ DWORD duplex_flags;
int err;
assert(handle->type == UV_NAMED_PIPE);
UNREGISTER_HANDLE_REQ(loop, handle, req);
- if (req->cb) {
- err = 0;
- if (REQ_SUCCESS(req)) {
- uv_pipe_connection_init(handle);
- } else {
- err = GET_REQ_ERROR(req);
- }
- req->cb(req, uv_translate_sys_error(err));
+ err = 0;
+ if (REQ_SUCCESS(req)) {
+ pipeHandle = req->u.connect.pipeHandle;
+ duplex_flags = req->u.connect.duplex_flags;
+ err = uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags);
+ if (err)
+ CloseHandle(pipeHandle);
+ } else {
+ err = uv_translate_sys_error(GET_REQ_ERROR(req));
}
+ if (req->cb)
+ req->cb(req, err);
+
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
+
+void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_shutdown_t* req) {
+ int err;
+
assert(handle->type == UV_NAMED_PIPE);
+ /* Clear the shutdown_req field so we don't go here again. */
+ handle->stream.conn.shutdown_req = NULL;
+ handle->flags &= ~UV_HANDLE_SHUTTING;
UNREGISTER_HANDLE_REQ(loop, handle, req);
- if (handle->flags & UV_HANDLE_READABLE) {
- /* Initialize and optionally start the eof timer. Only do this if the pipe
- * is readable and we haven't seen EOF come in ourselves. */
- eof_timer_init(handle);
+ if (handle->flags & UV_HANDLE_CLOSING) {
+ /* Already closing. Cancel the shutdown. */
+ err = UV_ECANCELED;
+ } else if (!REQ_SUCCESS(req)) {
+ /* An error occurred in trying to shutdown gracefully. */
+ err = uv_translate_sys_error(GET_REQ_ERROR(req));
+ } else {
+ if (handle->flags & UV_HANDLE_READABLE) {
+ /* Initialize and optionally start the eof timer. Only do this if the pipe
+ * is readable and we haven't seen EOF come in ourselves. */
+ eof_timer_init(handle);
+
+ /* If reading start the timer right now. Otherwise uv__pipe_queue_read will
+ * start it. */
+ if (handle->flags & UV_HANDLE_READ_PENDING) {
+ eof_timer_start(handle);
+ }
- /* If reading start the timer right now. Otherwise uv_pipe_queue_read will
- * start it. */
- if (handle->flags & UV_HANDLE_READ_PENDING) {
- eof_timer_start(handle);
+ } else {
+ /* This pipe is not readable. We can just close it to let the other end
+ * know that we're done writing. */
+ close_pipe(handle);
}
-
- } else {
- /* This pipe is not readable. We can just close it to let the other end
- * know that we're done writing. */
- close_pipe(handle);
+ err = 0;
}
- if (req->cb) {
- req->cb(req, 0);
- }
+ if (req->cb)
+ req->cb(req, err);
DECREASE_PENDING_REQ_COUNT(handle);
}
@@ -2200,7 +2194,8 @@ static void eof_timer_init(uv_pipe_t* pipe) {
pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);
r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);
- assert(r == 0); /* timers can't fail */
+ assert(r == 0); /* timers can't fail */
+ (void) r;
pipe->pipe.conn.eof_timer->data = pipe;
uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer);
}
@@ -2231,9 +2226,9 @@ static void eof_timer_cb(uv_timer_t* timer) {
assert(pipe->type == UV_NAMED_PIPE);
/* This should always be true, since we start the timer only in
- * uv_pipe_queue_read after successfully calling ReadFile, or in
- * uv_process_pipe_shutdown_req if a read is pending, and we always
- * immediately stop the timer in uv_process_pipe_read_req. */
+ * uv__pipe_queue_read after successfully calling ReadFile, or in
+ * uv__process_pipe_shutdown_req if a read is pending, and we always
+ * immediately stop the timer in uv__process_pipe_read_req. */
assert(pipe->flags & UV_HANDLE_READ_PENDING);
/* If there are many packets coming off the iocp then the timer callback may
@@ -2254,7 +2249,7 @@ static void eof_timer_cb(uv_timer_t* timer) {
/* Report the eof and update flags. This will get reported even if the user
* stopped reading in the meantime. TODO: is that okay? */
- uv_pipe_read_eof(loop, pipe, uv_null_buf_);
+ uv__pipe_read_eof(loop, pipe, uv_null_buf_);
}
@@ -2280,10 +2275,16 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
IO_STATUS_BLOCK io_status;
FILE_ACCESS_INFORMATION access;
DWORD duplex_flags = 0;
+ int err;
if (os_handle == INVALID_HANDLE_VALUE)
return UV_EBADF;
+ if (pipe->flags & UV_HANDLE_PIPESERVER)
+ return UV_EINVAL;
+ if (pipe->flags & UV_HANDLE_CONNECTION)
+ return UV_EBUSY;
+ uv__pipe_connection_init(pipe);
uv__once_init();
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
* underlying OS handle and forget about the original fd.
@@ -2300,6 +2301,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
FALSE,
DUPLICATE_SAME_ACCESS))
return uv_translate_sys_error(GetLastError());
+ assert(os_handle != INVALID_HANDLE_VALUE);
file = -1;
}
@@ -2327,17 +2329,17 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (access.AccessFlags & FILE_READ_DATA)
duplex_flags |= UV_HANDLE_READABLE;
- if (os_handle == INVALID_HANDLE_VALUE ||
- uv_set_pipe_handle(pipe->loop,
- pipe,
- os_handle,
- file,
- duplex_flags) == -1) {
- return UV_EINVAL;
+ err = uv__set_pipe_handle(pipe->loop,
+ pipe,
+ os_handle,
+ file,
+ duplex_flags);
+ if (err) {
+ if (file == -1)
+ CloseHandle(os_handle);
+ return err;
}
- uv_pipe_connection_init(pipe);
-
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
@@ -2361,6 +2363,51 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
uv__once_init();
name_info = NULL;
+ if (handle->name != NULL) {
+ /* The user might try to query the name before we are connected,
+ * and this is just easier to return the cached value if we have it. */
+ name_buf = handle->name;
+ name_len = wcslen(name_buf);
+
+ /* check how much space we need */
+ addrlen = WideCharToMultiByte(CP_UTF8,
+ 0,
+ name_buf,
+ name_len,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (!addrlen) {
+ *size = 0;
+ err = uv_translate_sys_error(GetLastError());
+ return err;
+ } else if (addrlen >= *size) {
+ *size = addrlen + 1;
+ err = UV_ENOBUFS;
+ goto error;
+ }
+
+ addrlen = WideCharToMultiByte(CP_UTF8,
+ 0,
+ name_buf,
+ name_len,
+ buffer,
+ addrlen,
+ NULL,
+ NULL);
+ if (!addrlen) {
+ *size = 0;
+ err = uv_translate_sys_error(GetLastError());
+ return err;
+ }
+
+ *size = addrlen;
+ buffer[addrlen] = '\0';
+
+ return 0;
+ }
+
if (handle->handle == INVALID_HANDLE_VALUE) {
*size = 0;
return UV_EINVAL;
@@ -2498,6 +2545,11 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
if (handle->handle != INVALID_HANDLE_VALUE)
return uv__pipe_getname(handle, buffer, size);
+ if (handle->flags & UV_HANDLE_CONNECTION) {
+ if (handle->name != NULL)
+ return uv__pipe_getname(handle, buffer, size);
+ }
+
return UV_EBADF;
}
diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c
index 9d3775960..bd531b067 100644
--- a/Utilities/cmlibuv/src/win/poll.c
+++ b/Utilities/cmlibuv/src/win/poll.c
@@ -34,7 +34,9 @@ static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
{0xf9eab0c0, 0x26d4, 0x11d0,
{0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
{0x9fc48064, 0x7298, 0x43e4,
- {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}
+ {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}},
+ {0xa00943d9, 0x9c2e, 0x4633,
+ {0x9b, 0x59, 0x00, 0x57, 0xa3, 0x16, 0x09, 0x94}}
};
typedef struct uv_single_fd_set_s {
@@ -122,14 +124,14 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped);
- result = uv_msafd_poll((SOCKET) handle->peer_socket,
- afd_poll_info,
- afd_poll_info,
- &req->u.io.overlapped);
+ result = uv__msafd_poll((SOCKET) handle->peer_socket,
+ afd_poll_info,
+ afd_poll_info,
+ &req->u.io.overlapped);
if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
/* Queue this req, reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
}
}
@@ -195,7 +197,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
}
@@ -357,7 +359,7 @@ static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
WT_EXECUTELONGFUNCTION)) {
/* Make this req pending, reporting an error. */
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
}
}
@@ -400,7 +402,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
}
@@ -524,7 +526,7 @@ int uv_poll_stop(uv_poll_t* handle) {
}
-void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
+void uv__process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
uv__fast_poll_process_poll_req(loop, handle, req);
} else {
@@ -533,7 +535,7 @@ void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
}
-int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
+int uv__poll_close(uv_loop_t* loop, uv_poll_t* handle) {
AFD_POLL_INFO afd_poll_info;
DWORD error;
int result;
@@ -543,7 +545,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
if (handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
return 0;
}
@@ -559,10 +561,10 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
afd_poll_info.Handles[0].Status = 0;
afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
- result = uv_msafd_poll(handle->socket,
- &afd_poll_info,
- uv__get_afd_poll_info_dummy(),
- uv__get_overlapped_dummy());
+ result = uv__msafd_poll(handle->socket,
+ &afd_poll_info,
+ uv__get_afd_poll_info_dummy(),
+ uv__get_overlapped_dummy());
if (result == SOCKET_ERROR) {
error = WSAGetLastError();
@@ -574,7 +576,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
}
-void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
+void uv__poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 9ca4122ca..248b7ea34 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -105,7 +105,7 @@ static void uv__init_global_job_handle(void) {
}
-static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
+static int uv__utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
int ws_len, r;
WCHAR* ws;
@@ -137,7 +137,7 @@ static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
}
-static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
+static void uv__process_init(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);
handle->exit_cb = NULL;
handle->pid = 0;
@@ -864,7 +864,7 @@ static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
/* Called on main thread after a child process has exited. */
-void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
+void uv__process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
int64_t exit_code;
DWORD status;
@@ -874,7 +874,7 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
/* If we're closing, don't call the exit callback. Just schedule a close
* callback now. */
if (handle->flags & UV_HANDLE_CLOSING) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
return;
}
@@ -902,7 +902,7 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
}
-void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
+void uv__process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_closing(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
@@ -918,12 +918,12 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
}
if (!handle->exit_cb_pending) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
+ uv__want_endgame(loop, (uv_handle_t*)handle);
}
}
-void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
+void uv__process_endgame(uv_loop_t* loop, uv_process_t* handle) {
assert(!handle->exit_cb_pending);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
@@ -948,7 +948,7 @@ int uv_spawn(uv_loop_t* loop,
PROCESS_INFORMATION info;
DWORD process_flags;
- uv_process_init(loop, process);
+ uv__process_init(loop, process);
process->exit_cb = options->exit_cb;
if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
@@ -975,7 +975,7 @@ int uv_spawn(uv_loop_t* loop,
UV_PROCESS_WINDOWS_HIDE_GUI |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
- err = uv_utf8_to_utf16_alloc(options->file, &application);
+ err = uv__utf8_to_utf16_alloc(options->file, &application);
if (err)
goto done;
@@ -994,7 +994,7 @@ int uv_spawn(uv_loop_t* loop,
if (options->cwd) {
/* Explicit cwd */
- err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);
+ err = uv__utf8_to_utf16_alloc(options->cwd, &cwd);
if (err)
goto done;
diff --git a/Utilities/cmlibuv/src/win/req-inl.h b/Utilities/cmlibuv/src/win/req-inl.h
index f2513b7d3..9e2075906 100644
--- a/Utilities/cmlibuv/src/win/req-inl.h
+++ b/Utilities/cmlibuv/src/win/req-inl.h
@@ -50,7 +50,7 @@
(pRtlNtStatusToDosError(GET_REQ_STATUS((req))))
#define GET_REQ_SOCK_ERROR(req) \
- (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req))))
+ (uv__ntstatus_to_winsock_error(GET_REQ_STATUS((req))))
#define REGISTER_HANDLE_REQ(loop, handle, req) \
@@ -82,12 +82,12 @@
}
-INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) {
+INLINE static uv_req_t* uv__overlapped_to_req(OVERLAPPED* overlapped) {
return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);
}
-INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
+INLINE static void uv__insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
req->next_req = NULL;
if (loop->pending_reqs_tail) {
#ifdef _DEBUG
@@ -115,19 +115,19 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
do { \
switch (((uv_handle_t*) (req)->handle_at)->type) { \
case UV_TCP: \
- uv_process_tcp_##method##_req(loop, \
+ uv__process_tcp_##method##_req(loop, \
(uv_tcp_t*) ((req)->handle_at), \
req); \
break; \
\
case UV_NAMED_PIPE: \
- uv_process_pipe_##method##_req(loop, \
+ uv__process_pipe_##method##_req(loop, \
(uv_pipe_t*) ((req)->handle_at), \
req); \
break; \
\
case UV_TTY: \
- uv_process_tty_##method##_req(loop, \
+ uv__process_tty_##method##_req(loop, \
(uv_tty_t*) ((req)->handle_at), \
req); \
break; \
@@ -138,13 +138,13 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
} while (0)
-INLINE static int uv_process_reqs(uv_loop_t* loop) {
+INLINE static void uv__process_reqs(uv_loop_t* loop) {
uv_req_t* req;
uv_req_t* first;
uv_req_t* next;
if (loop->pending_reqs_tail == NULL)
- return 0;
+ return;
first = loop->pending_reqs_tail->next_req;
next = first;
@@ -172,50 +172,43 @@ INLINE static int uv_process_reqs(uv_loop_t* loop) {
break;
case UV_SHUTDOWN:
- /* Tcp shutdown requests don't come here. */
- assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);
- uv_process_pipe_shutdown_req(
- loop,
- (uv_pipe_t*) ((uv_shutdown_t*) req)->handle,
- (uv_shutdown_t*) req);
+ DELEGATE_STREAM_REQ(loop, (uv_shutdown_t*) req, shutdown, handle);
break;
case UV_UDP_RECV:
- uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req);
+ uv__process_udp_recv_req(loop, (uv_udp_t*) req->data, req);
break;
case UV_UDP_SEND:
- uv_process_udp_send_req(loop,
- ((uv_udp_send_t*) req)->handle,
- (uv_udp_send_t*) req);
+ uv__process_udp_send_req(loop,
+ ((uv_udp_send_t*) req)->handle,
+ (uv_udp_send_t*) req);
break;
case UV_WAKEUP:
- uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req);
+ uv__process_async_wakeup_req(loop, (uv_async_t*) req->data, req);
break;
case UV_SIGNAL_REQ:
- uv_process_signal_req(loop, (uv_signal_t*) req->data, req);
+ uv__process_signal_req(loop, (uv_signal_t*) req->data, req);
break;
case UV_POLL_REQ:
- uv_process_poll_req(loop, (uv_poll_t*) req->data, req);
+ uv__process_poll_req(loop, (uv_poll_t*) req->data, req);
break;
case UV_PROCESS_EXIT:
- uv_process_proc_exit(loop, (uv_process_t*) req->data);
+ uv__process_proc_exit(loop, (uv_process_t*) req->data);
break;
case UV_FS_EVENT_REQ:
- uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
+ uv__process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
break;
default:
assert(0);
}
}
-
- return 1;
}
#endif /* UV_WIN_REQ_INL_H_ */
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index 3d9f92cfb..8c79871b9 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -39,7 +39,7 @@ int uv__signal_start(uv_signal_t* handle,
int signum,
int oneshot);
-void uv_signals_init(void) {
+void uv__signals_init(void) {
InitializeCriticalSection(&uv__signal_lock);
if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
abort();
@@ -231,7 +231,7 @@ int uv__signal_start(uv_signal_t* handle,
}
-void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
+void uv__process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
uv_req_t* req) {
long dispatched_signum;
@@ -254,22 +254,22 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
if (handle->flags & UV_HANDLE_CLOSING) {
/* When it is closing, it must be stopped at this point. */
assert(handle->signum == 0);
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
}
-void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {
+void uv__signal_close(uv_loop_t* loop, uv_signal_t* handle) {
uv_signal_stop(handle);
uv__handle_closing(handle);
if (handle->pending_signum == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
}
-void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
+void uv__signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h
index 40f5ddd51..91b1e785d 100644
--- a/Utilities/cmlibuv/src/win/stream-inl.h
+++ b/Utilities/cmlibuv/src/win/stream-inl.h
@@ -30,9 +30,9 @@
#include "req-inl.h"
-INLINE static void uv_stream_init(uv_loop_t* loop,
- uv_stream_t* handle,
- uv_handle_type type) {
+INLINE static void uv__stream_init(uv_loop_t* loop,
+ uv_stream_t* handle,
+ uv_handle_type type) {
uv__handle_init(loop, (uv_handle_t*) handle, type);
handle->write_queue_size = 0;
handle->activecnt = 0;
@@ -46,7 +46,7 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
}
-INLINE static void uv_connection_init(uv_stream_t* handle) {
+INLINE static void uv__connection_init(uv_stream_t* handle) {
handle->flags |= UV_HANDLE_CONNECTION;
}
diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c
index abf477f64..292bf588d 100644
--- a/Utilities/cmlibuv/src/win/stream.c
+++ b/Utilities/cmlibuv/src/win/stream.c
@@ -29,14 +29,16 @@
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
int err;
-
+ if (uv__is_closing(stream)) {
+ return UV_EINVAL;
+ }
err = ERROR_INVALID_PARAMETER;
switch (stream->type) {
case UV_TCP:
- err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
+ err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
+ err = uv__pipe_listen((uv_pipe_t*)stream, backlog, cb);
break;
default:
assert(0);
@@ -52,10 +54,10 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
err = ERROR_INVALID_PARAMETER;
switch (server->type) {
case UV_TCP:
- err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);
+ err = uv__tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_accept((uv_pipe_t*)server, client);
+ err = uv__pipe_accept((uv_pipe_t*)server, client);
break;
default:
assert(0);
@@ -73,13 +75,13 @@ int uv__read_start(uv_stream_t* handle,
err = ERROR_INVALID_PARAMETER;
switch (handle->type) {
case UV_TCP:
- err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
+ err = uv__tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
+ err = uv__pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
break;
case UV_TTY:
- err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb);
+ err = uv__tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb);
break;
default:
assert(0);
@@ -97,7 +99,7 @@ int uv_read_stop(uv_stream_t* handle) {
err = 0;
if (handle->type == UV_TTY) {
- err = uv_tty_read_stop((uv_tty_t*) handle);
+ err = uv__tty_read_stop((uv_tty_t*) handle);
} else if (handle->type == UV_NAMED_PIPE) {
uv__pipe_read_stop((uv_pipe_t*) handle);
} else {
@@ -124,14 +126,14 @@ int uv_write(uv_write_t* req,
err = ERROR_INVALID_PARAMETER;
switch (handle->type) {
case UV_TCP:
- err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
+ err = uv__tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
break;
case UV_NAMED_PIPE:
err = uv__pipe_write(
loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
break;
case UV_TTY:
- err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
+ err = uv__tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
break;
default:
assert(0);
@@ -217,7 +219,12 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
- uv_want_endgame(loop, (uv_handle_t*)handle);
+ if (handle->stream.conn.write_reqs_pending == 0) {
+ if (handle->type == UV_NAMED_PIPE)
+ uv__pipe_shutdown(loop, (uv_pipe_t*) handle, req);
+ else
+ uv__insert_pending_req(loop, (uv_req_t*) req);
+ }
return 0;
}
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 6ca11e070..b6aa4c512 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -78,11 +78,11 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
}
-static int uv_tcp_set_socket(uv_loop_t* loop,
- uv_tcp_t* handle,
- SOCKET socket,
- int family,
- int imported) {
+static int uv__tcp_set_socket(uv_loop_t* loop,
+ uv_tcp_t* handle,
+ SOCKET socket,
+ int family,
+ int imported) {
DWORD yes = 1;
int non_ifs_lsp;
int err;
@@ -162,7 +162,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
if (flags & ~0xFF)
return UV_EINVAL;
- uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);
+ uv__stream_init(loop, (uv_stream_t*) handle, UV_TCP);
handle->tcp.serv.accept_reqs = NULL;
handle->tcp.serv.pending_accepts = NULL;
handle->socket = INVALID_SOCKET;
@@ -173,7 +173,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
handle->delayed_error = 0;
/* If anything fails beyond this point we need to remove the handle from
- * the handle queue, since it was added by uv__handle_init in uv_stream_init.
+ * the handle queue, since it was added by uv__handle_init in uv__stream_init.
*/
if (domain != AF_UNSPEC) {
@@ -187,7 +187,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
return uv_translate_sys_error(err);
}
- err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0);
+ err = uv__tcp_set_socket(handle->loop, handle, sock, domain, 0);
if (err) {
closesocket(sock);
QUEUE_REMOVE(&handle->handle_queue);
@@ -205,73 +205,76 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
}
-void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
+void uv__process_tcp_shutdown_req(uv_loop_t* loop, uv_tcp_t* stream, uv_shutdown_t *req) {
int err;
- unsigned int i;
- uv_tcp_accept_t* req;
- if (handle->flags & UV_HANDLE_CONNECTION &&
- handle->stream.conn.shutdown_req != NULL &&
- handle->stream.conn.write_reqs_pending == 0) {
+ assert(req);
+ assert(stream->stream.conn.write_reqs_pending == 0);
+ assert(!(stream->flags & UV_HANDLE_SHUT));
+ assert(stream->flags & UV_HANDLE_CONNECTION);
- UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
+ stream->stream.conn.shutdown_req = NULL;
+ stream->flags &= ~UV_HANDLE_SHUTTING;
+ UNREGISTER_HANDLE_REQ(loop, stream, req);
- err = 0;
- if (handle->flags & UV_HANDLE_CLOSING) {
- err = ERROR_OPERATION_ABORTED;
- } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
- err = WSAGetLastError();
- }
+ err = 0;
+ if (stream->flags & UV_HANDLE_CLOSING)
+ /* The user destroyed the stream before we got to do the shutdown. */
+ err = UV_ECANCELED;
+ else if (shutdown(stream->socket, SD_SEND) == SOCKET_ERROR)
+ err = uv_translate_sys_error(WSAGetLastError());
+ else /* Success. */
+ stream->flags |= UV_HANDLE_SHUT;
+
+ if (req->cb)
+ req->cb(req, err);
- if (handle->stream.conn.shutdown_req->cb) {
- handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req,
- uv_translate_sys_error(err));
- }
+ DECREASE_PENDING_REQ_COUNT(stream);
+}
- handle->stream.conn.shutdown_req = NULL;
- DECREASE_PENDING_REQ_COUNT(handle);
- return;
- }
- if (handle->flags & UV_HANDLE_CLOSING &&
- handle->reqs_pending == 0) {
- assert(!(handle->flags & UV_HANDLE_CLOSED));
- assert(handle->socket == INVALID_SOCKET);
+void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
+ unsigned int i;
+ uv_tcp_accept_t* req;
+
+ assert(handle->flags & UV_HANDLE_CLOSING);
+ assert(handle->reqs_pending == 0);
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
+ assert(handle->socket == INVALID_SOCKET);
- if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
- if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- for (i = 0; i < uv_simultaneous_server_accepts; i++) {
- req = &handle->tcp.serv.accept_reqs[i];
- if (req->wait_handle != INVALID_HANDLE_VALUE) {
- UnregisterWait(req->wait_handle);
- req->wait_handle = INVALID_HANDLE_VALUE;
- }
- if (req->event_handle != NULL) {
- CloseHandle(req->event_handle);
- req->event_handle = NULL;
- }
+ if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
+ for (i = 0; i < uv_simultaneous_server_accepts; i++) {
+ req = &handle->tcp.serv.accept_reqs[i];
+ if (req->wait_handle != INVALID_HANDLE_VALUE) {
+ UnregisterWait(req->wait_handle);
+ req->wait_handle = INVALID_HANDLE_VALUE;
+ }
+ if (req->event_handle != NULL) {
+ CloseHandle(req->event_handle);
+ req->event_handle = NULL;
}
}
-
- uv__free(handle->tcp.serv.accept_reqs);
- handle->tcp.serv.accept_reqs = NULL;
}
- if (handle->flags & UV_HANDLE_CONNECTION &&
- handle->flags & UV_HANDLE_EMULATE_IOCP) {
- if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
- UnregisterWait(handle->read_req.wait_handle);
- handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
- }
- if (handle->read_req.event_handle != NULL) {
- CloseHandle(handle->read_req.event_handle);
- handle->read_req.event_handle = NULL;
- }
- }
+ uv__free(handle->tcp.serv.accept_reqs);
+ handle->tcp.serv.accept_reqs = NULL;
+ }
- uv__handle_close(handle);
- loop->active_tcp_streams--;
+ if (handle->flags & UV_HANDLE_CONNECTION &&
+ handle->flags & UV_HANDLE_EMULATE_IOCP) {
+ if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
+ UnregisterWait(handle->read_req.wait_handle);
+ handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
+ }
+ if (handle->read_req.event_handle != NULL) {
+ CloseHandle(handle->read_req.event_handle);
+ handle->read_req.event_handle = NULL;
+ }
}
+
+ uv__handle_close(handle);
+ loop->active_tcp_streams--;
}
@@ -286,10 +289,10 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
* See issue #1360.
*
*/
-static int uv_tcp_try_bind(uv_tcp_t* handle,
- const struct sockaddr* addr,
- unsigned int addrlen,
- unsigned int flags) {
+static int uv__tcp_try_bind(uv_tcp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen,
+ unsigned int flags) {
DWORD err;
int r;
@@ -305,7 +308,7 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
return WSAGetLastError();
}
- err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
+ err = uv__tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
if (err) {
closesocket(sock);
return err;
@@ -385,7 +388,7 @@ static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {
}
-static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
+static void uv__tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
uv_loop_t* loop = handle->loop;
BOOL success;
DWORD bytes;
@@ -406,7 +409,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
accept_socket = socket(family, SOCK_STREAM, 0);
if (accept_socket == INVALID_SOCKET) {
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
handle->reqs_pending++;
return;
}
@@ -414,7 +417,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
/* Make the socket non-inheritable */
if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
handle->reqs_pending++;
closesocket(accept_socket);
return;
@@ -440,7 +443,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
/* Process the req without IOCP. */
req->accept_socket = accept_socket;
handle->reqs_pending++;
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
/* The req will be processed with IOCP. */
req->accept_socket = accept_socket;
@@ -451,12 +454,12 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
req->event_handle, post_completion, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
handle->reqs_pending++;
/* Destroy the preallocated client socket. */
closesocket(accept_socket);
@@ -469,7 +472,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
}
-static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
+static void uv__tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
uv_read_t* req;
uv_buf_t buf;
int result;
@@ -524,7 +527,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Process the req without IOCP. */
req->u.io.overlapped.InternalHigh = bytes;
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
@@ -533,12 +536,12 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
req->event_handle, post_completion, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
}
@@ -558,7 +561,7 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
}
-int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
+int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
unsigned int i, simultaneous_accepts;
uv_tcp_accept_t* req;
int err;
@@ -578,10 +581,10 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
- err = uv_tcp_try_bind(handle,
- (const struct sockaddr*) &uv_addr_ip4_any_,
- sizeof(uv_addr_ip4_any_),
- 0);
+ err = uv__tcp_try_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip4_any_,
+ sizeof(uv_addr_ip4_any_),
+ 0);
if (err)
return err;
if (handle->delayed_error)
@@ -589,7 +592,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
}
if (!handle->tcp.serv.func_acceptex) {
- if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) {
+ if (!uv__get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) {
return WSAEAFNOSUPPORT;
}
}
@@ -630,7 +633,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
req->event_handle = NULL;
}
- uv_tcp_queue_accept(handle, req);
+ uv__tcp_queue_accept(handle, req);
}
/* Initialize other unused requests too, because uv_tcp_endgame doesn't
@@ -650,7 +653,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
}
-int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
+int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
uv_loop_t* loop = server->loop;
int err = 0;
int family;
@@ -672,7 +675,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
family = AF_INET;
}
- err = uv_tcp_set_socket(client->loop,
+ err = uv__tcp_set_socket(client->loop,
client,
req->accept_socket,
family,
@@ -680,7 +683,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
if (err) {
closesocket(req->accept_socket);
} else {
- uv_connection_init((uv_stream_t*) client);
+ uv__connection_init((uv_stream_t*) client);
/* AcceptEx() implicitly binds the accepted socket. */
client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}
@@ -693,7 +696,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
if (!(server->flags & UV_HANDLE_CLOSING)) {
/* Check if we're in a middle of changing the number of pending accepts. */
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
- uv_tcp_queue_accept(server, req);
+ uv__tcp_queue_accept(server, req);
} else {
/* We better be switching to a single pending accept. */
assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);
@@ -706,7 +709,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
* All previously queued accept requests are now processed.
* We now switch to queueing just a single accept.
*/
- uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);
+ uv__tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);
server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
}
@@ -719,7 +722,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
}
-int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
+int uv__tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb) {
uv_loop_t* loop = handle->loop;
@@ -738,7 +741,7 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
uv_fatal_error(GetLastError(), "CreateEvent");
}
}
- uv_tcp_queue_read(loop, handle);
+ uv__tcp_queue_read(loop, handle);
}
return 0;
@@ -779,7 +782,7 @@ static int uv__is_fast_loopback_fail_supported(void) {
return os_info.dwBuildNumber >= 16299;
}
-static int uv_tcp_try_connect(uv_connect_t* req,
+static int uv__tcp_try_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
@@ -807,7 +810,7 @@ static int uv_tcp_try_connect(uv_connect_t* req,
} else {
abort();
}
- err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);
+ err = uv__tcp_try_bind(handle, bind_addr, addrlen, 0);
if (err)
return err;
if (handle->delayed_error != 0)
@@ -815,7 +818,7 @@ static int uv_tcp_try_connect(uv_connect_t* req,
}
if (!handle->tcp.conn.func_connectex) {
- if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) {
+ if (!uv__get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) {
return WSAEAFNOSUPPORT;
}
}
@@ -850,7 +853,7 @@ out:
/* Process the req without IOCP. */
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
return 0;
}
@@ -866,7 +869,7 @@ out:
/* Process the req without IOCP. */
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
/* The req will be processed with IOCP. */
handle->reqs_pending++;
@@ -903,7 +906,7 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
}
-int uv_tcp_write(uv_loop_t* loop,
+int uv__tcp_write(uv_loop_t* loop,
uv_write_t* req,
uv_tcp_t* handle,
const uv_buf_t bufs[],
@@ -941,7 +944,7 @@ int uv_tcp_write(uv_loop_t* loop,
handle->reqs_pending++;
handle->stream.conn.write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
@@ -954,7 +957,7 @@ int uv_tcp_write(uv_loop_t* loop,
req->event_handle, post_write_completion, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
} else {
/* Send failed due to an error, report it later */
@@ -963,7 +966,7 @@ int uv_tcp_write(uv_loop_t* loop,
handle->stream.conn.write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
}
return 0;
@@ -994,7 +997,7 @@ int uv__tcp_try_write(uv_tcp_t* handle,
}
-void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_req_t* req) {
DWORD bytes, flags, err;
uv_buf_t buf;
@@ -1115,7 +1118,7 @@ done:
/* Post another read if still reading and not closing. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_tcp_queue_read(loop, handle);
+ uv__tcp_queue_read(loop, handle);
}
}
@@ -1123,7 +1126,7 @@ done:
}
-void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_write_t* req) {
int err;
@@ -1160,16 +1163,17 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
closesocket(handle->socket);
handle->socket = INVALID_SOCKET;
}
- if (handle->stream.conn.shutdown_req != NULL) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
- }
+ if (handle->flags & UV_HANDLE_SHUTTING)
+ uv__process_tcp_shutdown_req(loop,
+ handle,
+ handle->stream.conn.shutdown_req);
}
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_req_t* raw_req) {
uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req;
int err;
@@ -1209,7 +1213,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
closesocket(req->accept_socket);
req->accept_socket = INVALID_SOCKET;
if (handle->flags & UV_HANDLE_LISTENING) {
- uv_tcp_queue_accept(handle, req);
+ uv__tcp_queue_accept(handle, req);
}
}
@@ -1217,7 +1221,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
}
-void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
+void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_connect_t* req) {
int err;
@@ -1242,7 +1246,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
SO_UPDATE_CONNECT_CONTEXT,
NULL,
0) == 0) {
- uv_connection_init((uv_stream_t*)handle);
+ uv__connection_init((uv_stream_t*)handle);
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
loop->active_tcp_streams++;
} else {
@@ -1312,7 +1316,7 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp,
return WSAGetLastError();
}
- err = uv_tcp_set_socket(
+ err = uv__tcp_set_socket(
tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
if (err) {
closesocket(socket);
@@ -1323,7 +1327,7 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp,
tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
- uv_connection_init((uv_stream_t*)tcp);
+ uv__connection_init((uv_stream_t*)tcp);
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}
@@ -1404,14 +1408,14 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
}
-static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) {
+static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) {
SOCKET socket;
int non_ifs_lsp;
int reading;
int writing;
socket = tcp->socket;
- reading = tcp->flags & UV_HANDLE_READING;
+ reading = tcp->flags & UV_HANDLE_READ_PENDING;
writing = tcp->stream.conn.write_reqs_pending > 0;
if (!reading && !writing)
return;
@@ -1456,12 +1460,12 @@ static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) {
}
-void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
+void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
if (tcp->flags & UV_HANDLE_CONNECTION) {
- uv_tcp_try_cancel_reqs(tcp);
if (tcp->flags & UV_HANDLE_READING) {
uv_read_stop((uv_stream_t*) tcp);
}
+ uv__tcp_try_cancel_reqs(tcp);
} else {
if (tcp->tcp.serv.accept_reqs != NULL) {
/* First close the incoming sockets to cancel the accept operations before
@@ -1483,6 +1487,9 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
DECREASE_ACTIVE_COUNT(loop, tcp);
}
+ tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
+ uv__handle_closing(tcp);
+
/* If any overlapped req failed to cancel, calling `closesocket` now would
* cause Win32 to send an RST packet. Try to avoid that for writes, if
* possibly applicable, by waiting to process the completion notifications
@@ -1494,12 +1501,8 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
tcp->socket = INVALID_SOCKET;
}
- tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
- uv__handle_closing(tcp);
-
- if (tcp->reqs_pending == 0) {
- uv_want_endgame(tcp->loop, (uv_handle_t*)tcp);
- }
+ if (tcp->reqs_pending == 0)
+ uv__want_endgame(loop, (uv_handle_t*) tcp);
}
@@ -1520,7 +1523,7 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
return uv_translate_sys_error(GetLastError());
}
- err = uv_tcp_set_socket(handle->loop,
+ err = uv__tcp_set_socket(handle->loop,
handle,
sock,
protocol_info.iAddressFamily,
@@ -1537,7 +1540,7 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
saddr_len = sizeof(saddr);
if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {
/* Socket is already connected. */
- uv_connection_init((uv_stream_t*) handle);
+ uv__connection_init((uv_stream_t*) handle);
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}
}
@@ -1555,7 +1558,7 @@ int uv__tcp_bind(uv_tcp_t* handle,
unsigned int flags) {
int err;
- err = uv_tcp_try_bind(handle, addr, addrlen, flags);
+ err = uv__tcp_try_bind(handle, addr, addrlen, flags);
if (err)
return uv_translate_sys_error(err);
@@ -1573,7 +1576,7 @@ int uv__tcp_connect(uv_connect_t* req,
uv_connect_cb cb) {
int err;
- err = uv_tcp_try_connect(req, handle, addr, addrlen, cb);
+ err = uv__tcp_try_connect(req, handle, addr, addrlen, cb);
if (err)
return uv_translate_sys_error(err);
@@ -1634,7 +1637,7 @@ int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int f
goto wsaerror;
if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0))
goto error;
- if (!uv_get_acceptex_function(server, &func_acceptex)) {
+ if (!uv__get_acceptex_function(server, &func_acceptex)) {
err = WSAEAFNOSUPPORT;
goto cleanup;
}
diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c
index ea5dc04e9..d3b1c96b6 100644
--- a/Utilities/cmlibuv/src/win/thread.c
+++ b/Utilities/cmlibuv/src/win/thread.c
@@ -182,8 +182,9 @@ int uv_thread_create_ex(uv_thread_t* tid,
uv_thread_t uv_thread_self(void) {
+ uv_thread_t key;
uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
- uv_thread_t key = uv_key_get(&uv__current_thread_key);
+ key = uv_key_get(&uv__current_thread_key);
if (key == NULL) {
/* If the thread wasn't started by uv_thread_create (such as the main
* thread), we assign an id to it now. */
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 1b9d4f853..267ca6451 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -67,10 +67,10 @@
#define CURSOR_SIZE_SMALL 25
#define CURSOR_SIZE_LARGE 100
-static void uv_tty_capture_initial_style(
+static void uv__tty_capture_initial_style(
CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info,
CONSOLE_CURSOR_INFO* cursor_info);
-static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
+static void uv__tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
static int uv__cancel_read_console(uv_tty_t* handle);
@@ -163,7 +163,7 @@ static BOOL uv__need_check_vterm_state = TRUE;
static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED;
static void uv__determine_vterm_state(HANDLE handle);
-void uv_console_init(void) {
+void uv__console_init(void) {
if (uv_sem_init(&uv_tty_output_lock, 1))
abort();
uv__tty_console_handle = CreateFileW(L"CONOUT$",
@@ -238,16 +238,16 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
uv__determine_vterm_state(handle);
/* Remember the original console text attributes and cursor info. */
- uv_tty_capture_initial_style(&screen_buffer_info, &cursor_info);
+ uv__tty_capture_initial_style(&screen_buffer_info, &cursor_info);
- uv_tty_update_virtual_window(&screen_buffer_info);
+ uv__tty_update_virtual_window(&screen_buffer_info);
uv_sem_post(&uv_tty_output_lock);
}
- uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY);
- uv_connection_init((uv_stream_t*) tty);
+ uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
+ uv__connection_init((uv_stream_t*) tty);
tty->handle = handle;
tty->u.fd = fd;
@@ -289,7 +289,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
/* Set the default console text attributes based on how the console was
* configured when libuv started.
*/
-static void uv_tty_capture_initial_style(
+static void uv__tty_capture_initial_style(
CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info,
CONSOLE_CURSOR_INFO* cursor_info) {
static int style_captured = 0;
@@ -380,7 +380,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
was_reading = 1;
alloc_cb = tty->alloc_cb;
read_cb = tty->read_cb;
- err = uv_tty_read_stop(tty);
+ err = uv__tty_read_stop(tty);
if (err) {
return uv_translate_sys_error(err);
}
@@ -404,7 +404,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
/* If we just stopped reading, restart. */
if (was_reading) {
- err = uv_tty_read_start(tty, alloc_cb, read_cb);
+ err = uv__tty_read_start(tty, alloc_cb, read_cb);
if (err) {
return uv_translate_sys_error(err);
}
@@ -422,7 +422,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
}
uv_sem_wait(&uv_tty_output_lock);
- uv_tty_update_virtual_window(&info);
+ uv__tty_update_virtual_window(&info);
uv_sem_post(&uv_tty_output_lock);
*width = uv_tty_virtual_width;
@@ -452,7 +452,7 @@ static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) {
}
-static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {
+static void uv__tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {
uv_read_t* req;
BOOL r;
@@ -475,7 +475,7 @@ static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {
if (!r) {
handle->tty.rd.read_raw_wait = NULL;
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
handle->flags |= UV_HANDLE_READ_PENDING;
@@ -579,7 +579,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
}
-static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
+static void uv__tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
uv_read_t* req;
BOOL r;
@@ -611,7 +611,7 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
WT_EXECUTELONGFUNCTION);
if (!r) {
SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
}
handle->flags |= UV_HANDLE_READ_PENDING;
@@ -619,11 +619,11 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
}
-static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
+static void uv__tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
if (handle->flags & UV_HANDLE_TTY_RAW) {
- uv_tty_queue_read_raw(loop, handle);
+ uv__tty_queue_read_raw(loop, handle);
} else {
- uv_tty_queue_read_line(loop, handle);
+ uv__tty_queue_read_line(loop, handle);
}
}
@@ -947,7 +947,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Wait for more input events. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_tty_queue_read(loop, handle);
+ uv__tty_queue_read(loop, handle);
}
DECREASE_PENDING_REQ_COUNT(handle);
@@ -992,14 +992,14 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
/* Wait for more input events. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_tty_queue_read(loop, handle);
+ uv__tty_queue_read(loop, handle);
}
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* req) {
assert(handle->type == UV_TTY);
assert(handle->flags & UV_HANDLE_TTY_READABLE);
@@ -1015,7 +1015,7 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
}
-int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
+int uv__tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb) {
uv_loop_t* loop = handle->loop;
@@ -1038,20 +1038,20 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
* Short-circuit if this could be the case. */
if (handle->tty.rd.last_key_len > 0) {
SET_REQ_SUCCESS(&handle->read_req);
- uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
+ uv__insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
/* Make sure no attempt is made to insert it again until it's handled. */
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
return 0;
}
- uv_tty_queue_read(loop, handle);
+ uv__tty_queue_read(loop, handle);
return 0;
}
-int uv_tty_read_stop(uv_tty_t* handle) {
+int uv__tty_read_stop(uv_tty_t* handle) {
INPUT_RECORD record;
DWORD written, err;
@@ -1137,7 +1137,7 @@ static int uv__cancel_read_console(uv_tty_t* handle) {
}
-static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
+static void uv__tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
uv_tty_virtual_width = info->dwSize.X;
uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
@@ -1160,12 +1160,12 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
}
-static COORD uv_tty_make_real_coord(uv_tty_t* handle,
+static COORD uv__tty_make_real_coord(uv_tty_t* handle,
CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y,
unsigned char y_relative) {
COORD result;
- uv_tty_update_virtual_window(info);
+ uv__tty_update_virtual_window(info);
/* Adjust y position */
if (y_relative) {
@@ -1197,7 +1197,7 @@ static COORD uv_tty_make_real_coord(uv_tty_t* handle,
}
-static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,
+static int uv__tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,
DWORD* error) {
DWORD written;
@@ -1218,7 +1218,7 @@ static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,
}
-static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
+static int uv__tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
int y, unsigned char y_relative, DWORD* error) {
CONSOLE_SCREEN_BUFFER_INFO info;
COORD pos;
@@ -1232,7 +1232,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
*error = GetLastError();
}
- pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative);
+ pos = uv__tty_make_real_coord(handle, &info, x, x_relative, y, y_relative);
if (!SetConsoleCursorPosition(handle->handle, pos)) {
if (GetLastError() == ERROR_INVALID_PARAMETER) {
@@ -1248,7 +1248,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
}
-static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
+static int uv__tty_reset(uv_tty_t* handle, DWORD* error) {
const COORD origin = {0, 0};
const WORD char_attrs = uv_tty_default_text_attributes;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
@@ -1300,7 +1300,7 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
/* Move the virtual window up to the top. */
uv_tty_virtual_offset = 0;
- uv_tty_update_virtual_window(&screen_buffer_info);
+ uv__tty_update_virtual_window(&screen_buffer_info);
/* Reset the cursor size and the cursor state. */
if (!SetConsoleCursorInfo(handle->handle, &uv_tty_default_cursor_info)) {
@@ -1312,7 +1312,7 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
}
-static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
+static int uv__tty_clear(uv_tty_t* handle, int dir, char entire_screen,
DWORD* error) {
CONSOLE_SCREEN_BUFFER_INFO info;
COORD start, end;
@@ -1341,7 +1341,7 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
x2r = 1;
} else {
/* Clear to end of row. We pretend the console is 65536 characters wide,
- * uv_tty_make_real_coord will clip it to the actual console width. */
+ * uv__tty_make_real_coord will clip it to the actual console width. */
x2 = 0xffff;
x2r = 0;
}
@@ -1364,8 +1364,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
return -1;
}
- start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r);
- end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r);
+ start = uv__tty_make_real_coord(handle, &info, x1, x1r, y1, y1r);
+ end = uv__tty_make_real_coord(handle, &info, x2, x2r, y2, y2r);
count = (end.Y * info.dwSize.X + end.X) -
(start.Y * info.dwSize.X + start.X) + 1;
@@ -1400,7 +1400,7 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
info.wAttributes |= bg >> 4; \
} while (0)
-static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
+static int uv__tty_set_style(uv_tty_t* handle, DWORD* error) {
unsigned short argc = handle->tty.wr.ansi_csi_argc;
unsigned short* argv = handle->tty.wr.ansi_csi_argv;
int i;
@@ -1556,7 +1556,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
}
-static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
+static int uv__tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
DWORD* error) {
CONSOLE_SCREEN_BUFFER_INFO info;
@@ -1569,10 +1569,11 @@ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
return -1;
}
- uv_tty_update_virtual_window(&info);
+ uv__tty_update_virtual_window(&info);
handle->tty.wr.saved_position.X = info.dwCursorPosition.X;
- handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset;
+ handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y -
+ uv_tty_virtual_offset;
handle->flags |= UV_HANDLE_TTY_SAVED_POSITION;
if (save_attributes) {
@@ -1585,7 +1586,7 @@ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
}
-static int uv_tty_restore_state(uv_tty_t* handle,
+static int uv__tty_restore_state(uv_tty_t* handle,
unsigned char restore_attributes, DWORD* error) {
CONSOLE_SCREEN_BUFFER_INFO info;
WORD new_attributes;
@@ -1595,7 +1596,7 @@ static int uv_tty_restore_state(uv_tty_t* handle,
}
if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) {
- if (uv_tty_move_caret(handle,
+ if (uv__tty_move_caret(handle,
handle->tty.wr.saved_position.X,
0,
handle->tty.wr.saved_position.Y,
@@ -1625,7 +1626,7 @@ static int uv_tty_restore_state(uv_tty_t* handle,
return 0;
}
-static int uv_tty_set_cursor_visibility(uv_tty_t* handle,
+static int uv__tty_set_cursor_visibility(uv_tty_t* handle,
BOOL visible,
DWORD* error) {
CONSOLE_CURSOR_INFO cursor_info;
@@ -1645,7 +1646,7 @@ static int uv_tty_set_cursor_visibility(uv_tty_t* handle,
return 0;
}
-static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) {
+static int uv__tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) {
CONSOLE_CURSOR_INFO cursor_info;
if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) {
@@ -1670,7 +1671,7 @@ static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) {
}
-static int uv_tty_write_bufs(uv_tty_t* handle,
+static int uv__tty_write_bufs(uv_tty_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
DWORD* error) {
@@ -1683,7 +1684,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
#define FLUSH_TEXT() \
do { \
if (utf16_buf_used > 0) { \
- uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
+ uv__tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
utf16_buf_used = 0; \
} \
} while (0)
@@ -1802,21 +1803,21 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case 'c':
/* Full console reset. */
FLUSH_TEXT();
- uv_tty_reset(handle, error);
+ uv__tty_reset(handle, error);
ansi_parser_state = ANSI_NORMAL;
continue;
case '7':
/* Save the cursor position and text attributes. */
FLUSH_TEXT();
- uv_tty_save_state(handle, 1, error);
+ uv__tty_save_state(handle, 1, error);
ansi_parser_state = ANSI_NORMAL;
continue;
case '8':
/* Restore the cursor position and text attributes */
FLUSH_TEXT();
- uv_tty_restore_state(handle, 1, error);
+ uv__tty_restore_state(handle, 1, error);
ansi_parser_state = ANSI_NORMAL;
continue;
@@ -1849,7 +1850,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
? handle->tty.wr.ansi_csi_argv[0] : 1;
if (style >= 0 && style <= 6) {
FLUSH_TEXT();
- uv_tty_set_cursor_shape(handle, style, error);
+ uv__tty_set_cursor_shape(handle, style, error);
}
}
@@ -1947,7 +1948,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
if (handle->tty.wr.ansi_csi_argc == 1 &&
handle->tty.wr.ansi_csi_argv[0] == 25) {
FLUSH_TEXT();
- uv_tty_set_cursor_visibility(handle, 0, error);
+ uv__tty_set_cursor_visibility(handle, 0, error);
}
break;
@@ -1956,7 +1957,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
if (handle->tty.wr.ansi_csi_argc == 1 &&
handle->tty.wr.ansi_csi_argv[0] == 25) {
FLUSH_TEXT();
- uv_tty_set_cursor_visibility(handle, 1, error);
+ uv__tty_set_cursor_visibility(handle, 1, error);
}
break;
}
@@ -1970,7 +1971,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
y = -(handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1);
- uv_tty_move_caret(handle, 0, 1, y, 1, error);
+ uv__tty_move_caret(handle, 0, 1, y, 1, error);
break;
case 'B':
@@ -1978,7 +1979,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
y = handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1;
- uv_tty_move_caret(handle, 0, 1, y, 1, error);
+ uv__tty_move_caret(handle, 0, 1, y, 1, error);
break;
case 'C':
@@ -1986,7 +1987,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
x = handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1;
- uv_tty_move_caret(handle, x, 1, 0, 1, error);
+ uv__tty_move_caret(handle, x, 1, 0, 1, error);
break;
case 'D':
@@ -1994,7 +1995,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
x = -(handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1);
- uv_tty_move_caret(handle, x, 1, 0, 1, error);
+ uv__tty_move_caret(handle, x, 1, 0, 1, error);
break;
case 'E':
@@ -2002,7 +2003,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
y = handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1;
- uv_tty_move_caret(handle, 0, 0, y, 1, error);
+ uv__tty_move_caret(handle, 0, 0, y, 1, error);
break;
case 'F':
@@ -2010,7 +2011,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
y = -(handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 1);
- uv_tty_move_caret(handle, 0, 0, y, 1, error);
+ uv__tty_move_caret(handle, 0, 0, y, 1, error);
break;
case 'G':
@@ -2019,7 +2020,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
x = (handle->tty.wr.ansi_csi_argc >= 1 &&
handle->tty.wr.ansi_csi_argv[0])
? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;
- uv_tty_move_caret(handle, x, 0, 0, 1, error);
+ uv__tty_move_caret(handle, x, 0, 0, 1, error);
break;
case 'H':
@@ -2032,7 +2033,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
x = (handle->tty.wr.ansi_csi_argc >= 2 &&
handle->tty.wr.ansi_csi_argv[1])
? handle->tty.wr.ansi_csi_argv[1] - 1 : 0;
- uv_tty_move_caret(handle, x, 0, y, 0, error);
+ uv__tty_move_caret(handle, x, 0, y, 0, error);
break;
case 'J':
@@ -2041,7 +2042,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
d = handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 0;
if (d >= 0 && d <= 2) {
- uv_tty_clear(handle, d, 1, error);
+ uv__tty_clear(handle, d, 1, error);
}
break;
@@ -2051,26 +2052,26 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
d = handle->tty.wr.ansi_csi_argc
? handle->tty.wr.ansi_csi_argv[0] : 0;
if (d >= 0 && d <= 2) {
- uv_tty_clear(handle, d, 0, error);
+ uv__tty_clear(handle, d, 0, error);
}
break;
case 'm':
/* Set style */
FLUSH_TEXT();
- uv_tty_set_style(handle, error);
+ uv__tty_set_style(handle, error);
break;
case 's':
/* Save the cursor position. */
FLUSH_TEXT();
- uv_tty_save_state(handle, 0, error);
+ uv__tty_save_state(handle, 0, error);
break;
case 'u':
/* Restore the cursor position */
FLUSH_TEXT();
- uv_tty_restore_state(handle, 0, error);
+ uv__tty_restore_state(handle, 0, error);
break;
}
}
@@ -2179,7 +2180,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
}
-int uv_tty_write(uv_loop_t* loop,
+int uv__tty_write(uv_loop_t* loop,
uv_write_t* req,
uv_tty_t* handle,
const uv_buf_t bufs[],
@@ -2197,13 +2198,13 @@ int uv_tty_write(uv_loop_t* loop,
req->u.io.queued_bytes = 0;
- if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) {
+ if (!uv__tty_write_bufs(handle, bufs, nbufs, &error)) {
SET_REQ_SUCCESS(req);
} else {
SET_REQ_ERROR(req, error);
}
- uv_insert_pending_req(loop, (uv_req_t*) req);
+ uv__insert_pending_req(loop, (uv_req_t*) req);
return 0;
}
@@ -2217,14 +2218,14 @@ int uv__tty_try_write(uv_tty_t* handle,
if (handle->stream.conn.write_reqs_pending > 0)
return UV_EAGAIN;
- if (uv_tty_write_bufs(handle, bufs, nbufs, &error))
+ if (uv__tty_write_bufs(handle, bufs, nbufs, &error))
return uv_translate_sys_error(error);
return uv__count_bufs(bufs, nbufs);
}
-void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req) {
int err;
@@ -2236,20 +2237,22 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
req->cb(req, uv_translate_sys_error(err));
}
+
handle->stream.conn.write_reqs_pending--;
- if (handle->stream.conn.shutdown_req != NULL &&
- handle->stream.conn.write_reqs_pending == 0) {
- uv_want_endgame(loop, (uv_handle_t*)handle);
- }
+ if (handle->stream.conn.write_reqs_pending == 0)
+ if (handle->flags & UV_HANDLE_SHUTTING)
+ uv__process_tty_shutdown_req(loop,
+ handle,
+ handle->stream.conn.shutdown_req);
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_tty_close(uv_tty_t* handle) {
+void uv__tty_close(uv_tty_t* handle) {
assert(handle->u.fd == -1 || handle->u.fd > 2);
if (handle->flags & UV_HANDLE_READING)
- uv_tty_read_stop(handle);
+ uv__tty_read_stop(handle);
if (handle->u.fd == -1)
CloseHandle(handle->handle);
@@ -2261,61 +2264,61 @@ void uv_tty_close(uv_tty_t* handle) {
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
uv__handle_closing(handle);
- if (handle->reqs_pending == 0) {
- uv_want_endgame(handle->loop, (uv_handle_t*) handle);
- }
+ if (handle->reqs_pending == 0)
+ uv__want_endgame(handle->loop, (uv_handle_t*) handle);
}
-void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
- if (!(handle->flags & UV_HANDLE_TTY_READABLE) &&
- handle->stream.conn.shutdown_req != NULL &&
- handle->stream.conn.write_reqs_pending == 0) {
- UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
+void uv__process_tty_shutdown_req(uv_loop_t* loop, uv_tty_t* stream, uv_shutdown_t* req) {
+ assert(stream->stream.conn.write_reqs_pending == 0);
+ assert(req);
- /* TTY shutdown is really just a no-op */
- if (handle->stream.conn.shutdown_req->cb) {
- if (handle->flags & UV_HANDLE_CLOSING) {
- handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
- } else {
- handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
- }
+ stream->stream.conn.shutdown_req = NULL;
+ stream->flags &= ~UV_HANDLE_SHUTTING;
+ UNREGISTER_HANDLE_REQ(loop, stream, req);
+
+ /* TTY shutdown is really just a no-op */
+ if (req->cb) {
+ if (stream->flags & UV_HANDLE_CLOSING) {
+ req->cb(req, UV_ECANCELED);
+ } else {
+ req->cb(req, 0);
}
+ }
- handle->stream.conn.shutdown_req = NULL;
+ DECREASE_PENDING_REQ_COUNT(stream);
+}
- DECREASE_PENDING_REQ_COUNT(handle);
- return;
- }
- if (handle->flags & UV_HANDLE_CLOSING &&
- handle->reqs_pending == 0) {
- /* The wait handle used for raw reading should be unregistered when the
- * wait callback runs. */
- assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
- handle->tty.rd.read_raw_wait == NULL);
+void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
+ assert(handle->flags & UV_HANDLE_CLOSING);
+ assert(handle->reqs_pending == 0);
- assert(!(handle->flags & UV_HANDLE_CLOSED));
- uv__handle_close(handle);
- }
+ /* The wait handle used for raw reading should be unregistered when the
+ * wait callback runs. */
+ assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
+ handle->tty.rd.read_raw_wait == NULL);
+
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
+ uv__handle_close(handle);
}
/*
- * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
* TODO: find a way to remove it
*/
-void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req) {
abort();
}
/*
- * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
* TODO: find a way to remove it
*/
-void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
+void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req) {
abort();
}
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index 7b5efa27e..eaebc1eda 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -60,7 +60,7 @@ int uv_udp_getsockname(const uv_udp_t* handle,
}
-static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
+static int uv__udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
int family) {
DWORD yes = 1;
WSAPROTOCOL_INFOW info;
@@ -106,8 +106,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
FILE_SKIP_SET_EVENT_ON_HANDLE |
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
- handle->func_wsarecv = uv_wsarecv_workaround;
- handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
+ handle->func_wsarecv = uv__wsarecv_workaround;
+ handle->func_wsarecvfrom = uv__wsarecvfrom_workaround;
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
return GetLastError();
}
@@ -155,7 +155,7 @@ int uv__udp_init_ex(uv_loop_t* loop,
return uv_translate_sys_error(err);
}
- err = uv_udp_set_socket(handle->loop, handle, sock, domain);
+ err = uv__udp_set_socket(handle->loop, handle, sock, domain);
if (err) {
closesocket(sock);
QUEUE_REMOVE(&handle->handle_queue);
@@ -167,7 +167,7 @@ int uv__udp_init_ex(uv_loop_t* loop,
}
-void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
+void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle) {
uv_udp_recv_stop(handle);
closesocket(handle->socket);
handle->socket = INVALID_SOCKET;
@@ -175,12 +175,12 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
uv__handle_closing(handle);
if (handle->reqs_pending == 0) {
- uv_want_endgame(loop, (uv_handle_t*) handle);
+ uv__want_endgame(loop, (uv_handle_t*) handle);
}
}
-void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
+void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
@@ -194,10 +194,10 @@ int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
}
-static int uv_udp_maybe_bind(uv_udp_t* handle,
- const struct sockaddr* addr,
- unsigned int addrlen,
- unsigned int flags) {
+static int uv__udp_maybe_bind(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen,
+ unsigned int flags) {
int r;
int err;
DWORD no = 0;
@@ -216,7 +216,7 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
return WSAGetLastError();
}
- err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family);
+ err = uv__udp_set_socket(handle->loop, handle, sock, addr->sa_family);
if (err) {
closesocket(sock);
return err;
@@ -264,7 +264,7 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
}
-static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
+static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
uv_req_t* req;
uv_buf_t buf;
DWORD bytes, flags;
@@ -311,7 +311,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
handle->flags |= UV_HANDLE_READ_PENDING;
req->u.io.overlapped.InternalHigh = bytes;
handle->reqs_pending++;
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
@@ -319,7 +319,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
handle->reqs_pending++;
}
@@ -343,7 +343,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
handle->flags |= UV_HANDLE_READ_PENDING;
req->u.io.overlapped.InternalHigh = bytes;
handle->reqs_pending++;
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
@@ -351,7 +351,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
- uv_insert_pending_req(loop, req);
+ uv__insert_pending_req(loop, req);
handle->reqs_pending++;
}
}
@@ -367,10 +367,10 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
return UV_EALREADY;
}
- err = uv_udp_maybe_bind(handle,
- (const struct sockaddr*) &uv_addr_ip4_any_,
- sizeof(uv_addr_ip4_any_),
- 0);
+ err = uv__udp_maybe_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip4_any_,
+ sizeof(uv_addr_ip4_any_),
+ 0);
if (err)
return uv_translate_sys_error(err);
@@ -384,7 +384,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
/* If reading was stopped and then started again, there could still be a recv
* request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
- uv_udp_queue_recv(loop, handle);
+ uv__udp_queue_recv(loop, handle);
return 0;
}
@@ -433,7 +433,7 @@ static int uv__send(uv_udp_send_t* req,
handle->send_queue_size += req->u.io.queued_bytes;
handle->send_queue_count++;
REGISTER_HANDLE_REQ(loop, handle, req);
- uv_insert_pending_req(loop, (uv_req_t*)req);
+ uv__insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
@@ -450,7 +450,7 @@ static int uv__send(uv_udp_send_t* req,
}
-void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
+void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
uv_req_t* req) {
uv_buf_t buf;
int partial;
@@ -554,14 +554,14 @@ done:
/* Post another read if still reading and not closing. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_udp_queue_recv(loop, handle);
+ uv__udp_queue_recv(loop, handle);
}
DECREASE_PENDING_REQ_COUNT(handle);
}
-void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
+void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
uv_udp_send_t* req) {
int err;
@@ -598,10 +598,10 @@ static int uv__udp_set_membership4(uv_udp_t* handle,
return UV_EINVAL;
/* If the socket is unbound, bind to inaddr_any. */
- err = uv_udp_maybe_bind(handle,
- (const struct sockaddr*) &uv_addr_ip4_any_,
- sizeof(uv_addr_ip4_any_),
- UV_UDP_REUSEADDR);
+ err = uv__udp_maybe_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip4_any_,
+ sizeof(uv_addr_ip4_any_),
+ UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
@@ -652,10 +652,10 @@ int uv__udp_set_membership6(uv_udp_t* handle,
if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
return UV_EINVAL;
- err = uv_udp_maybe_bind(handle,
- (const struct sockaddr*) &uv_addr_ip6_any_,
- sizeof(uv_addr_ip6_any_),
- UV_UDP_REUSEADDR);
+ err = uv__udp_maybe_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip6_any_,
+ sizeof(uv_addr_ip6_any_),
+ UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
@@ -708,10 +708,10 @@ static int uv__udp_set_source_membership4(uv_udp_t* handle,
return UV_EINVAL;
/* If the socket is unbound, bind to inaddr_any. */
- err = uv_udp_maybe_bind(handle,
- (const struct sockaddr*) &uv_addr_ip4_any_,
- sizeof(uv_addr_ip4_any_),
- UV_UDP_REUSEADDR);
+ err = uv__udp_maybe_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip4_any_,
+ sizeof(uv_addr_ip4_any_),
+ UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
@@ -763,10 +763,10 @@ int uv__udp_set_source_membership6(uv_udp_t* handle,
if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
return UV_EINVAL;
- err = uv_udp_maybe_bind(handle,
- (const struct sockaddr*) &uv_addr_ip6_any_,
- sizeof(uv_addr_ip6_any_),
- UV_UDP_REUSEADDR);
+ err = uv__udp_maybe_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip6_any_,
+ sizeof(uv_addr_ip6_any_),
+ UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
@@ -962,10 +962,10 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return uv_translate_sys_error(GetLastError());
}
- err = uv_udp_set_socket(handle->loop,
- handle,
- sock,
- protocol_info.iAddressFamily);
+ err = uv__udp_set_socket(handle->loop,
+ handle,
+ sock,
+ protocol_info.iAddressFamily);
if (err)
return uv_translate_sys_error(err);
@@ -1044,7 +1044,7 @@ int uv__udp_bind(uv_udp_t* handle,
unsigned int flags) {
int err;
- err = uv_udp_maybe_bind(handle, addr, addrlen, flags);
+ err = uv__udp_maybe_bind(handle, addr, addrlen, flags);
if (err)
return uv_translate_sys_error(err);
@@ -1066,7 +1066,7 @@ int uv__udp_connect(uv_udp_t* handle,
else
return UV_EINVAL;
- err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
}
@@ -1117,7 +1117,7 @@ int uv__udp_send(uv_udp_send_t* req,
else
return UV_EINVAL;
- err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
}
@@ -1146,6 +1146,7 @@ int uv__udp_try_send(uv_udp_t* handle,
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
if (err)
return err;
+ addr = (const struct sockaddr*) &converted;
}
/* Already sending a message.*/
@@ -1159,7 +1160,7 @@ int uv__udp_try_send(uv_udp_t* handle,
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
- err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
}
@@ -1169,7 +1170,7 @@ int uv__udp_try_send(uv_udp_t* handle,
nbufs,
&bytes,
0,
- (const struct sockaddr*) &converted,
+ addr,
addrlen,
NULL,
NULL);
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 33e874ac4..99432053c 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -531,103 +531,25 @@ int uv_resident_set_memory(size_t* rss) {
int uv_uptime(double* uptime) {
- BYTE stack_buffer[4096];
- BYTE* malloced_buffer = NULL;
- BYTE* buffer = (BYTE*) stack_buffer;
- size_t buffer_size = sizeof(stack_buffer);
- DWORD data_size;
-
- PERF_DATA_BLOCK* data_block;
- PERF_OBJECT_TYPE* object_type;
- PERF_COUNTER_DEFINITION* counter_definition;
-
- DWORD i;
-
- for (;;) {
- LONG result;
-
- data_size = (DWORD) buffer_size;
- result = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
- L"2",
- NULL,
- NULL,
- buffer,
- &data_size);
- if (result == ERROR_SUCCESS) {
- break;
- } else if (result != ERROR_MORE_DATA) {
- *uptime = 0;
- return uv_translate_sys_error(result);
- }
-
- buffer_size *= 2;
- /* Don't let the buffer grow infinitely. */
- if (buffer_size > 1 << 20) {
- goto internalError;
- }
-
- uv__free(malloced_buffer);
-
- buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size);
- if (malloced_buffer == NULL) {
- *uptime = 0;
- return UV_ENOMEM;
- }
- }
-
- if (data_size < sizeof(*data_block))
- goto internalError;
-
- data_block = (PERF_DATA_BLOCK*) buffer;
-
- if (wmemcmp(data_block->Signature, L"PERF", 4) != 0)
- goto internalError;
-
- if (data_size < data_block->HeaderLength + sizeof(*object_type))
- goto internalError;
-
- object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength);
-
- if (object_type->NumInstances != PERF_NO_INSTANCES)
- goto internalError;
+ *uptime = GetTickCount64() / 1000.0;
+ return 0;
+}
- counter_definition = (PERF_COUNTER_DEFINITION*) (buffer +
- data_block->HeaderLength + object_type->HeaderLength);
- for (i = 0; i < object_type->NumCounters; i++) {
- if ((BYTE*) counter_definition + sizeof(*counter_definition) >
- buffer + data_size) {
- break;
- }
- if (counter_definition->CounterNameTitleIndex == 674 &&
- counter_definition->CounterSize == sizeof(uint64_t)) {
- if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size ||
- !(counter_definition->CounterType & PERF_OBJECT_TIMER)) {
- goto internalError;
- } else {
- BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
- counter_definition->CounterOffset;
- uint64_t value = *((uint64_t*) address);
- *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
- (double) object_type->PerfFreq.QuadPart);
- uv__free(malloced_buffer);
- return 0;
- }
- }
+unsigned int uv_available_parallelism(void) {
+ SYSTEM_INFO info;
+ unsigned rc;
- counter_definition = (PERF_COUNTER_DEFINITION*)
- ((BYTE*) counter_definition + counter_definition->ByteLength);
- }
+ /* TODO(bnoordhuis) Use GetLogicalProcessorInformationEx() to support systems
+ * with > 64 CPUs? See https://github.com/libuv/libuv/pull/3458
+ */
+ GetSystemInfo(&info);
- /* If we get here, the uptime value was not found. */
- uv__free(malloced_buffer);
- *uptime = 0;
- return UV_ENOSYS;
+ rc = info.dwNumberOfProcessors;
+ if (rc < 1)
+ rc = 1;
- internalError:
- uv__free(malloced_buffer);
- *uptime = 0;
- return UV_EIO;
+ return rc;
}
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index bf306cd83..53147b826 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -48,7 +48,7 @@ sSetWinEventHook pSetWinEventHook;
/* ws2_32.dll function pointer */
uv_sGetHostNameW pGetHostNameW;
-void uv_winapi_init(void) {
+void uv__winapi_init(void) {
HMODULE ntdll_module;
HMODULE powrprof_module;
HMODULE user32_module;
@@ -126,19 +126,19 @@ void uv_winapi_init(void) {
kernel32_module,
"GetQueuedCompletionStatusEx");
- powrprof_module = LoadLibraryA("powrprof.dll");
+ powrprof_module = LoadLibraryExA("powrprof.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (powrprof_module != NULL) {
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification");
}
- user32_module = LoadLibraryA("user32.dll");
+ user32_module = GetModuleHandleA("user32.dll");
if (user32_module != NULL) {
pSetWinEventHook = (sSetWinEventHook)
GetProcAddress(user32_module, "SetWinEventHook");
}
- ws2_32_module = LoadLibraryA("ws2_32.dll");
+ ws2_32_module = GetModuleHandleA("ws2_32.dll");
if (ws2_32_module != NULL) {
pGetHostNameW = (uv_sGetHostNameW) GetProcAddress(
ws2_32_module,
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index 4cf6e6b04..a68b09536 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -38,7 +38,7 @@ struct sockaddr_in6 uv_addr_ip6_any_;
/*
* Retrieves the pointer to a winsock extension function.
*/
-static BOOL uv_get_extension_function(SOCKET socket, GUID guid,
+static BOOL uv__get_extension_function(SOCKET socket, GUID guid,
void **target) {
int result;
DWORD bytes;
@@ -62,20 +62,20 @@ static BOOL uv_get_extension_function(SOCKET socket, GUID guid,
}
-BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) {
+BOOL uv__get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) {
const GUID wsaid_acceptex = WSAID_ACCEPTEX;
- return uv_get_extension_function(socket, wsaid_acceptex, (void**)target);
+ return uv__get_extension_function(socket, wsaid_acceptex, (void**)target);
}
-BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {
+BOOL uv__get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {
const GUID wsaid_connectex = WSAID_CONNECTEX;
- return uv_get_extension_function(socket, wsaid_connectex, (void**)target);
+ return uv__get_extension_function(socket, wsaid_connectex, (void**)target);
}
-void uv_winsock_init(void) {
+void uv__winsock_init(void) {
WSADATA wsa_data;
int errorno;
SOCKET dummy;
@@ -134,7 +134,7 @@ void uv_winsock_init(void) {
}
-int uv_ntstatus_to_winsock_error(NTSTATUS status) {
+int uv__ntstatus_to_winsock_error(NTSTATUS status) {
switch (status) {
case STATUS_SUCCESS:
return ERROR_SUCCESS;
@@ -267,7 +267,7 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) {
* the user to use the default msafd driver, doesn't work when other LSPs are
* stacked on top of it.
*/
-int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
+int WSAAPI uv__wsarecv_workaround(SOCKET socket, WSABUF* buffers,
DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
NTSTATUS status;
@@ -346,7 +346,7 @@ int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
break;
default:
- error = uv_ntstatus_to_winsock_error(status);
+ error = uv__ntstatus_to_winsock_error(status);
break;
}
@@ -360,8 +360,8 @@ int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
}
-/* See description of uv_wsarecv_workaround. */
-int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
+/* See description of uv__wsarecv_workaround. */
+int WSAAPI uv__wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
int* addr_len, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
@@ -444,7 +444,7 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
break;
default:
- error = uv_ntstatus_to_winsock_error(status);
+ error = uv__ntstatus_to_winsock_error(status);
break;
}
@@ -458,7 +458,7 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
}
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+int WSAAPI uv__msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {
IO_STATUS_BLOCK iosb;
IO_STATUS_BLOCK* iosb_ptr;
@@ -531,7 +531,7 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
break;
default:
- error = uv_ntstatus_to_winsock_error(status);
+ error = uv__ntstatus_to_winsock_error(status);
break;
}
diff --git a/Utilities/std/cmext/enum_set b/Utilities/std/cmext/enum_set
index 4225b825a..d7b8b39b8 100644
--- a/Utilities/std/cmext/enum_set
+++ b/Utilities/std/cmext/enum_set
@@ -146,6 +146,7 @@ public:
{
this->Set.reset();
this->insert(list);
+ return *this;
}
// Iterators
@@ -298,17 +299,15 @@ public:
{
if (this->contains(e)) {
return iterator(this, static_cast<size_type>(e));
- } else {
- return this->end();
}
+ return this->end();
}
const_iterator find(key_type e) const
{
if (this->contains(e)) {
return const_iterator(this, static_cast<size_type>(e));
- } else {
- return this->end();
}
+ return this->end();
}
bool contains(key_type e) const
@@ -317,6 +316,10 @@ public:
}
private:
+ template <typename E>
+ friend inline bool operator==(const enum_set<E>& lhs,
+ const enum_set<E>& rhs) noexcept;
+
template <typename E, typename Predicate>
friend inline void erase_if(enum_set<E>& set, Predicate pred);
@@ -369,7 +372,7 @@ template <typename Enum>
inline bool operator==(const enum_set<Enum>& lhs,
const enum_set<Enum>& rhs) noexcept
{
- return lhs == rhs;
+ return lhs.Set == rhs.Set;
}
template <typename Enum>
diff --git a/bootstrap b/bootstrap
index 9a8741398..ea9816cf1 100755
--- a/bootstrap
+++ b/bootstrap
@@ -281,6 +281,7 @@ CMAKE_UNUSED_SOURCES="\
"
CMAKE_CXX_SOURCES="\
+ cmAddCompileDefinitionsCommand \
cmAddCustomCommandCommand \
cmAddCustomTargetCommand \
cmAddDefinitionsCommand \
@@ -301,6 +302,7 @@ CMAKE_CXX_SOURCES="\
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool \
cmBinUtilsWindowsPELinker \
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \
+ cmBlockCommand \
cmBreakCommand \
cmBuildCommand \
cmCMakeLanguageCommand \
@@ -328,6 +330,7 @@ CMAKE_CXX_SOURCES="\
cmCustomCommand \
cmCustomCommandGenerator \
cmCustomCommandLines \
+ cmCxxModuleMapper \
cmDefinePropertyCommand \
cmDefinitions \
cmDocumentationFormatter \
@@ -337,6 +340,7 @@ CMAKE_CXX_SOURCES="\
cmExecProgramCommand \
cmExecuteProcessCommand \
cmExpandedCommandArgument \
+ cmExperimental \
cmExportBuildFileGenerator \
cmExportFileGenerator \
cmExportInstallFileGenerator \
@@ -391,6 +395,7 @@ CMAKE_CXX_SOURCES="\
cmIncludeRegularExpressionCommand \
cmInstallCommand \
cmInstallCommandArguments \
+ cmInstallCxxModuleBmiGenerator \
cmInstallDirectoryGenerator \
cmInstallExportGenerator \
cmInstallFileSetGenerator \
@@ -588,6 +593,7 @@ if ${cmake_system_mingw}; then
src/inet.c \
src/threadpool.c \
src/strscpy.c \
+ src/strtok.c \
src/timer.c \
src/uv-common.c \
src/win/async.c \
@@ -618,6 +624,7 @@ if ${cmake_system_mingw}; then
else
LIBUV_C_SOURCES="\
src/strscpy.c \
+ src/strtok.c \
src/timer.c \
src/uv-common.c \
src/unix/cmake-bootstrap.c \
@@ -634,6 +641,7 @@ else
src/unix/signal.c \
src/unix/stream.c \
src/unix/tcp.c \
+ src/unix/tty.c \
"
fi